43

I create a react library using https://www.npmjs.com/package/create-react-library And successfully used it on other React project. But when I tried to use react hooks functionalities inside library it gives me following error.

Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
    1. You might have mismatching versions of React and the renderer (such as 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
.....

My Library I just tried to use useState as follows in my component.

import React, { useState } from 'react'

const General = (props) => {

    const [count, setCount] = useState(0);
    return (
        <div>
           General component
        </div>
    )
}

export default General

I am using "react": "^16.8.6" and "react-dom": "^16.8.6"

My React APP Created a application using https://github.com/facebook/create-react-app and used above library as follows.

import Reactfrom 'react'
import { General } from 'my.lib'
const accountSummary = props => {

  return (
    <div>
      <General>
    </div>
  )
}

export default accountSummary

Both has same react versions and library has used same react-dom and react versions as peerDependencies

11
  • What versions of React and React DOM are you using?
    – Joe Clay
    May 7, 2019 at 11:04
  • The component looks ok. Check your React and React DOM version 16.8 (I assume that's is ok too). can you provide the whole minimum code to reproduce it? I have been trying to reproduce and I can't
    – F.bernal
    May 7, 2019 at 11:20
  • 1
    The issue is with I am running the library locally and has refer it using ` "my.library": "file:../my.library"` in py package.json. Lib is running separately in another react instance. If I publish it as npm library and use it works fine. May 8, 2019 at 9:18
  • 1
    This is how you broke the rule ... You used a hook (say useState) in one of the component(of MyLibrary), which is bundled to dist/index.js by your Rollup (which is by default configured by create-react-library). When the bundling happened Your hook might got pushed to one of the condition (say if) and the rule broke!! Aug 6, 2019 at 22:19
  • 2
    @YugandharPathi if that's the case, what is the solution? I think I may be having the same issue. React can't be so fragile that it cant handle bundling, can it?
    – Dave
    Jul 12, 2020 at 20:16

10 Answers 10

70

I was including my component library (for that matter any library) in my application as @Janith did using my-comp-lib:"file:../.." (I don't want to publish every time I want to test) and I encountered the same issue.

Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as 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 See react-invalid-hook-call for tips about how to debug and

fix this problem

I was able to fix this by making my app and library point to the same react (package) location.

Below are the steps I followed :
1. In Your Application:
a) cd node_modules/react && npm link
b) cd node_modules/react-dom && npm link

2. In Your Library
a) npm link react
b) npm link react-dom

3)Stop your dev-server and do `npm start` again.

It works!!

Please refer below links for more details ..

https://github.com/facebook/react/issues/14721

https://github.com/facebook/react/pull/14690

https://github.com/facebook/react/issues/13991

Note : This issue will not happen if you publish your package to artifactory and install because you will have react & react-dom as peer-dependencies and they won't get included in the distribution. So your package and application use the same react which is installed in the application.

6
  • Does react-dom need to be installed in the library? It is not explicitly imported in the library code that the OP wrote.
    – kas
    May 27, 2020 at 2:09
  • 3
    By the way, a more concise solution is to run this command from the library folder: "npm link ../web-application/node_modules/react". This is assuming the library and web application are in sibling folders. A similar command can be used if the library also needs to use react-dom.
    – kas
    May 27, 2020 at 2:11
  • 2
    @yugandhar-pathi thanks a lot for this solution !
    – jashgopani
    May 18, 2021 at 6:13
  • 2
    Thanks for this answer. It really helped
    – vdua
    Jul 15, 2021 at 16:55
  • Thank you for your solution @yugandhar-pathi! but there is a question: we are not publishing our package into npm! we put it on our gitlab server and then install it on other applications using gitlab deploy token. how can we handle this in production? we can not use npm link in production Jul 18, 2021 at 7:35
7

I just ran into the same issue. I was able to fix it by pointing to the same react in my example app as in my library:

App Structure

Root

  • Example
    • package.json
  • src (library)
  • package.json

So, from the example > package.json I changed react to be:

    "react": "link:../node_modules/react",

This is much like the npm link listed above but it won't go away every time you npm install.

2
  • Yes, this was the solution for me to get rid of the above issue. Sep 11, 2019 at 10:24
  • 4
    Be aware that newer versions of npm have deprecated link. Instead you need to use file: "react": "file:../node_modules/react"
    – RyanNerd
    May 15, 2021 at 20:46
6

I had the same issue, working with a rush monorepo, configuring ui-package and building the apps using nextjs.

The solutions was add the follow code on package.json

"resolutions": {
  "react": "17.0.1", // verificate your react version
  "react-dom": "17.0.1"
}

In the library's package.json:

"peerDependencies": {
   "react": "17.0.1",
   "react-dom": "17.0.1"
 },

See more here: https://github.com/vercel/next.js/issues/9022#issuecomment-728688452

1
5

Add to your Components Library's package.json

"peerDependencies": {
  "react": "<your version>"
}

so that your lib package will use the same react package as your main app. https://nodejs.org/es/blog/npm/peer-dependencies/

0

It worked for me when I changed the link from the app to the library to be "link:../" instead of "file:../", in addition to linking react and react-dom.

1
  • 3
    I get an error "Unsupported URL Type "link:": when I try this. I'm on npm 6.4.1 Jun 23, 2020 at 17:39
0

React 17 + React Testing Library + Umi(a frontend framework, built-in react-router)

In my case, when I run the unit test, I got an error message "invalid hook call".

After a period of trying, I found two ways to solve.

  1. Downgrade to React 16.x, then all will be fine.
  2. Keep using React 17.x, and
    • Still have to write import React from 'react'
    • Install react-router-dom separately

I think it may be a problem with react-router, but due to my limited understanding, I don't have a better solution yet.

0

Also check your npm version. My version was 7.0.8 which was outdated, after changing it to 6.14.8 everything was working fine!

0

WHEN TESTING WITH REAL APP IN REACT NATIVE

I have same issue and i delete my node_module file in my custom library and i fixed it..

issue when installing direct module

yarn add c:/user......./react-native-some-lib

0

In my case I'm building my own common library. Although I was exporting createContext, useContext and useState from "react", I simply forgot to also import the default export, React.

Changing my import statement from this:
import { createContext, useContext, useState } from "react";

to this:
import React, { createContext, useContext, useState } from "react";

fixed it for me. You might have to do this in every React component/context etc that you are exporting from your react library.

Edit:

In another one of my apps that relies on this common library, this issue was also fixed using npm link as described in the React documentation (Invalid Hook Call Warning):

This problem can also come up when you use npm link or an equivalent. In that case, your bundler might “see” two Reacts — one in application folder and one in your library folder. 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.

So in my case, I navigated to my common library and ran npm link ../path-to-my-app/node_modules/react.

Edit (23/02/2022)

Hopefully the final edit - another solution is to simply globally install the problem dependency if all apps expect to use the same version, e.g. npm install react -g

-2

I have created a React library with create-react-library this library is your General component. I have published it to npm here https://www.npmjs.com/package/stackoverflow-test and a React app for use it here https://codesandbox.io/s/mm7yl83o28.

Just click on General component text and count will be incremented.

I cannot reproduce your issue, just use this test to check your implementation.

6
  • Finally I found the issue. I installed "react-scripts" to my react app and it works fine now. May 7, 2019 at 14:29
  • Nice, so there was missing packets
    – F.bernal
    May 7, 2019 at 14:39
  • The issue is with I am running the library locally and has refer it using ` "my.library": "file:../my.library"`. Lib is running separately in another react instance. If I publish it as npm library and use it works fine. May 8, 2019 at 9:18
  • Did you use hook inside component (say <General/> ) in stackoverflow-test ? Aug 6, 2019 at 22:21
  • @YugandharPathi yes
    – F.bernal
    Aug 7, 2019 at 5:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.