score:25

Accepted answer

"Hooks can only be called inside the body of a function component."

Let's rule out all possibilities according to React docs:

  1. You might have mismatching versions of React and React DOM.

  2. You might be breaking the Rules of Hooks.

  3. You might have more than one copy of React in the same app.

1.) If unsure, try to reinstall react and react-dom in the latest version in your app, so they 100% match (or look at your package-lock.json / yarn lock):

npm i react@latest react-dom@latest

2.) Your useEffect Hook usage inside Test looks fine - Test is a function component and useEffect is called at the top-level.

3.) It would be my main guess for the error at hand.

You are using npm link to link the library for local tests. npm link will add a symbolic link for the complete library working directory (including node_modules) inside app project's node_modules. react is installed both as devDependencies in the library and as dependencies in the app project.

Now, when Webpack bundles the app project, it will choose react either from library or app - whichever is included in the nearest node_modules folder relative to the importing module.

Solution

A fix is mentioned on the Invalid Hook Call Warning page:

Assuming myapp and mylib are sibling folders, one possible fix is to run npm link ../myapp/node_modules/react from mylib. This should make the library use the application’s React copy.

Alternative: Tell Webpack to always resolve to a single react package - the one in your app node_modules (credit goes to these two issues). webpack.config.js:

resolve: {
  ...
  alias: {
    // Needed when library is linked via `npm link` to app
    react: path.resolve("./node_modules/react")
  }
}

"require is not defined"

This likely happens, when you run the web app bundled by a faulty Webpack config, where require calls are not dropped and replaced by the actual code modules.

If the application project is based on create-react-app, you might import the library in app and just run start or build. Given a custom Webpack config (e.g. via eject), run the build with target:web (or omit target) and leave out externals: [ nodeExternals() ].

score:0

Have you tried changing your target from node to web? That may cause some issues.

Also don't know all the details behind where you plan to use your library but something as simple as babel ./src --out-dir ./core --copy-files can be useful when you are using your library in an environment where you already have a build step that handles bundling.

I'd add a comment, but uh rep.

score:1

Is it just that you're trying to use your library in React apps running older versions of React that aren't compatible with hooks?

I just made a new create-react-app, added your repo as a dependency with yarn add https://github.com/uchami/hooks-not-working, and had no problem adding the Test component to the default App.js.

I only got an error after rolling back my app's version of React.

score:1

This might help too: React hooks duplicate react package

I had the very same problem but even worse, I have to manage multiple apps with their own libs.

The solution proposed solves all 'multiple react libs' errors


Related Query

More Query from same tag