React hooks in react library giving Invalid hook call error - reactjs

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

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:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
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.

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.

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

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/

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.

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.
Downgrade to React 16.x, then all will be fine.
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.

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!

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

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

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.

Related

A react app inside a monorepo (lerna) package causing conflicting 'react' package

I created :
A reusable react component package, and
A react app for testing the component
Both of them are inside a monorepo (lerna).
The problem is the "react" packages for the component & for the app are pointed to "different thing", thus using hook inside the component triggers this error:
"Hooks can only be called inside the body of a function component".
Deleting the second "react" package directory will affect to the component project because it's a symbolic linking (similar to shortcut to component project).
Any idea for resolving my problem?
clean all the node_modules.
use peer dependencies in react component.
l use that two steps slove react version conflict problem in monorepo.
You can try it.

Visual Studio React template project - Error: Invalid hook call

I am using the React web application template in Visual Studio 2022 to create a web project.
Right after project is created, I installed a component that's implemented with hooks, e.g. React-Bootstrap by package management command -
npm install react-bootstrap bootstrap#5.1.3
Then I import it to home.js -
import Button from 'react-bootstrap/Button';
and add an element -
<div>
<Button variant="primary">Button #1</Button>
<Button variant="secondary" className="mx-2">Button #2</Button>
<Button variant="success">Button #3</Button>
</div>
Run the project and I get the following error -
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 See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
I haven't added any other code and I think there is something wrong with the code in the template but I can't figure out the issue.
Looks like the React code generated by the template was using older react 16.0 and the home.js is still a class based component.
Upgrade react and react-dom by command "npm install react" and "npm install react-dom" (upgraded to 16.14) and also change the Home.js component to be a function based component solved my problem.

How do I import a React library from one Yarn workspace into another when hoisting is disabled?

I'm using Yarn v2 (berry) to manage a monorepo with the following structure:
project-root
/packages
react-native-app
(dependencies: my-hooks-lib, react#17.0.1)
my-hooks-lib
(dependency: react#17.0.1)
Here's my .yarnrc.yml:
yarnPath: ".yarn/releases/yarn-berry.cjs"
nodeLinker: "node-modules"
nmHoistingLimits: "workspaces"
I've disabled hoisting since I'm working with a React Native app. But because of this, react-native-app and my-hooks-lib have separate copies of react#17.0.1, even though the versions are the same. This results in a Invalid Hooks call error:
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
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
This is because my-hooks-lib uses a different copy of React, even though the version is the same. It works fine if I import React like this:
// inside my-hooks-lib
import React from "../react-native-app/node_modules/react";
I made React a peer-dependency inside my-hooks-lib, but that didn't help either, since Yarn creates a symlink to my-hooks-lib inside react-native-app, but it isn't able to resolve React. I then installed React as a dev-dependency at the root of my project, and now I'm back to my original problem, since now my-hooks-lib refers to the copy of React at the project root.
Is there a way to fix this during development?
Update: As a workaround, I've made React as a peer-dependency for both react-native-app and my-hooks-lib, and added React as a dev-dependency at the project root. So this is what it looks like now:
<project-root>
(dev-dependency: react#17.0.1)
/packages
/react-native-app
(dependency: my-hooks-lib, peer-dependency: react#17.0.1)
/my-hooks-lib
(peer-dependency: react#17.0.1)
Although I'd still love to hear a better solution!

Use two different React/React-Dom versions in project

I'm in an extremely weird situation where the project structure looks like:
Project
MiniProject1
MiniProject2
node_modules
package.json
The mini projects themselves are react apps that get shown within a ruby container. So when a user goes to /route1 it loads the miniProject1 react page. when they go to /route2 it goes to the miniProject2 page.
I've been tasked to update the react version of MiniProject2 but not interfere with MiniProject1 or make any changes that could interfere with MiniProject1.
I went the route of installing react and react-dom as follows:
"react-latest": "npm:react#^16.13.1",
"react-dom-latest": "npm:react-dom#^16.13.1",
so I can then import the latest versions specifically in MiniProject2
The problem that I'm facing is the react-dom has the "React" a peer dependency and it's trying to pull the project react instead of my aliased "react-latest" which makes sense but now I'm stuck trying to figure out how I can force react-dom to require my react-latest alias instead of the default react peer dependency.
I'm also open to potential Webpack config solutions.
Any thoughts?
After some digging I was able to force react-dom to use react-latest by doing the following:
package.json
"react": "^16.3.2",
"react-dom": "16.3.3",
"react-dom-latest": "npm:react-dom#^16.13.1",
"react-latest": "npm:react#^16.13.1",
webpack.config.js
module: {
rules: [
{
test: /\/node_modules\/react-dom-latest\/.*.js/,
resolve: {
alias: {
react: path.resolve('./node_modules/react-latest')
}
}
}]},
Then on the top of the files I need to use the latest react version for, I import react like so:
import React from 'react-latest'
//or
import ReactDOM from 'react-dom-latest' //for your index
On the files I need to use the old react for, I import react like so:
import React from 'react'
//or
import ReactDOM from 'react-dom' //for your index
That's all that needed to be done!
Disclaimer: Don't do this unless you have to and have no choice like I did. It'll increase the size of your bundle since you are bringing in two different versions of react and reactDom

create-react-library not working with styled components

I'm using create-react-library to build my component library, and I've attempted to use Styled Components, but I keep getting a React hooks error.
Here's my code: https://github.com/emmabostian/component-library
And here's the error:
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
I am not using React hooks anywhere, my React and React DOM versions match and I do not have multiple versions of React.
Check your package.json file you appear to have dependencies react / react-dom version 16 but peer dependencies for versions 15 . I think this is the cause of your problem , remove the peer dependencies. Also you don't need to write your components as class based if all you are doing is rendering use a functional component approach instead.
The dependencies in the included example project are very outdated.
Instead I set up a new separate example project, which perfectly renders your button:
npx create-react-app component-library-example
cd component-library-example
npm install --save emmas-super-cool-component-library
npm start
App.js:
import React from "react";
import { PrimaryButton } from "emmas-super-cool-component-library";
const App = () => (
<PrimaryButton
onClickHandler={() => {
alert("clicked");
}}
>
text
</PrimaryButton>
);
export default App;
Result:
I've recently used create-react-library, and had encountered the same issue. The error message exactly makes sense in this case. The issue will not happen when you actually publish the package and consume it at a consumer application. This means, the problem is with your example folder. If you look at package.json, that's inside example folder, you can see there are library references for react, react-scripts, react-dom etc. Referring those with file protocol like below will solve your problem.
"dependencies": {
"library-name": "file:..",
"react": "file:../node_modules/react",
"react-dom": "file:../node_modules/react-dom",
"react-scripts": "file:../node_modules/react-scripts"
"node-sass": "file:../node_modules/node-sass"
},
Clear your node_modules as well as package-lock.json before trying this.

Resources