node.js - Ugyldig hook-kall på npm-link-bibliotek


Problembeskrivelse:

  • Jeg holder for øyeblikket på å lage en pakke kalt eformless

  • Jeg har brukt CRA til å lage en katalog kalt sandbox, hvor jeg koblet pakken.

  • Jeg får stadig følgende feil når jeg prøver å starte sandbox React-appen med den tilknyttede pakken som jeg prøver å teste:

    // inside my 'sandbox' App.tsx
    import React from 'react'
    import { useField } from 'eformless'
    
    const App = () => {
      const [test, handleChange] = useField('testing')
      return (
        <input type="text" value={test.value} onChange={handleChange} />
      )
    }
    

Feil: Ugyldig hook-kall. Hooks kan kun kalles inne i kroppen til en funksjonskomponent. Dette kan skje av en av følgende grunner:

  1. Du kan ha ulike versjoner av React og renderer (for eksempel React DOM)
  2. Du kan bryte Regler for Hooks
  3. Du kan ha mer enn én kopi av React i samme app. Se endret lenke på grunn av Stack Overflow sine bruksvilkår for tips om hvordan du kan feilsøke og fikse dette problemet.

Hvor problemet oppstår:

Problemet ser ut til å peke på biblioteket mitt, der jeg har skrevet en tilpasset hook som bruker hooks importert fra React.
Her er det problematiske utdraget fra koden min:

export const useField = <T>(
  input: T
  ...checkFunctions: Array<(...args: unknown[]) => unknown>
): [FieldType<T>, FieldHandlerFunction<T>, FieldHandlerFunction<T>] => {
  const [value, setValue] = useState(input)
  const [name, setName] = useState('')
  // Issue seems to be here ^
}

Oppsettet mitt var ganske normalt og ser ut til å fungere bra i andre prosjekter:

  • Først bundlet jeg biblioteket mitt via rollup -c
  • Opprettet en lenke inne i min eformless-bibliotekmappe via npm link
  • Og opprettet symlinken inne i sandbox-mappen min via npm link eformless

Det jeg prøvde:

Jeg prøvde naturlig å løse problemet via lenken som ble gitt i feilmeldingen. Dette ser ut til å være et problem når man lenker til sitt eget bibliotek, som nevnt her

Dette problemet kan også oppstå når du bruker npm link eller en tilsvarende kommando. I så fall kan din bundler «se» to React-versjoner — en i applikasjonsmappen og en i bibliotekmappen din. Forutsatt at myapp og mylib er søstermapper, er en mulig løsning å kjøre npm link ../myapp/node_modules/react fra mylib. Dette bør få biblioteket til å bruke applikasjonens kopi av React.

Jeg kjørte npm link ../sandbox/node_modules/react i min eformless-mappe, men dette virket ikke å hjelpe, selv etter å ha stengt node-serveren og kompilert på nytt.

Uansett virker det virkelig forvirrende for meg, fordi å kjøre npm ls react bare viser en enkelt versjon av react og det burde være gyldig, gitt at useState brukes på øverste nivå inne i en egendefinert hook.

Reprodusere problemet

Begge lagringsstedene er offentlige

  • eformless bibliotekrepo
  • sandbox repo

Svar #1

  1. Du kan ha mer enn én kopi av React i samme app. Se endret lenke på grunn av Stack Overflow sine bruksvilkår for tips om hvordan du kan feilsøke og fikse dette problemet.

Det er fordi du har react i dine devDependencies for eformless. Dette får applikasjonen din til å kjøre to forekomster av React.

I stedet, flytt react til peer dependencies i eformless package.json, slett node_modules-mappen din og kjør npm install.

Ved å legge til react i peer-avhengigheter, informerer du modulbundleren din om å ikke inkludere react, men i stedet forvente at react vil bli gjort tilgjengelig for den av den avhengige applikasjonen.

"peerDependencies": {
  "react": "^16.13.1"
}

Jeg la også merke til at du hadde sjekket inn node_modules-katalogen din i eformless. Det bør du ikke gjøre. I stedet bør du legge til node_modules i .gitignore-filen din.

Svar #2

Bare i tilfelle det er nyttig for andre, brukte jeg allerede React som en 'peer-avhengighet' i biblioteket mitt, og fikk fortsatt dette problemet.

Jeg måtte utføre følgende trinn for å løse det:

På biblioteket:

  1. Hvis du ikke har gjort det allerede, sett opp bibliotekene som genererer problemer som peerDependencies i package.json i stedet for dependencies eller devDependencies, for eksempel i mitt tilfelle react:
"peerDependencies": {
  "react": "^16.8.6",
  ...
}
  1. kjør npm install
  2. bygg biblioteket (i mitt tilfelle, med et rollup -c npm-skript)

I hovedappen min:

  1. endre versjonen av biblioteket mitt for å peke til mitt lokale prosjekt med en relativ sti i package.json, f.eks.
"dependencies": {
  "my-library": "file:../../libraries/my-library",
  ...
}
  1. Legg til resolve.symlinks=false i hovedapplikasjonens webpack-konfigurasjon

  2. Legg til --preserve-symlinks-main og --preserve-symlinks i min package.json startskript, f.eks:

"scripts": {
  "build": "set WEBPACK_CONFIG_FILE=all&& webpack",
  "start": "set WEBPACK_CONFIG_FILE=all&& webpack && node --preserve-symlinks-main --preserve-symlinks dist/server.js",
}
  1. kjør npm install
  2. kjør npm run start

Relaterte artikler