If I use react hooks inside a page or component
import Comp from '../../comp
in nextjs everything work fine, if I use react hooks inside a component in an external library
import { Comp } from 'my-components
I get this error:
Hooks can only be called inside the body of a function component
this is my nextjs.config:
// next.config.js
const path = require('path');
const withTM = require('next-transpile-modules');
module.exports = withTM({
useFileSystemPublicRoutes: false,
transpileModules: ['ui-components'],
webpack: (config, options) => {
config.resolve.alias = {
...config.resolve.alias,
'styled-components': path.resolve(__dirname, '.', 'node_modules', 'styled-components'),
'react-dom': path.resolve(__dirname, '.', 'node_modules', 'react-dom'),
'react': path.resolve(__dirname, '.', 'node_modules', 'react'),
};
return config;
},
});
thie is the babelrc in my app:
{
"presets": [
"next/babel"
],
"plugins": [
[
"styled-components",
{
"ssr": true,
"displayName": true
}
]
]
}
this is the babelrc of my library:
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
],
"plugins": [
[
"babel-plugin-styled-components",
{
"ssr": true,
"displayName": true
}
],
"@babel/proposal-object-rest-spread"
],
"env": {
"module": {
"presets": [
[
"@babel/preset-env",
{
"modules": false
}
],
"@babel/preset-react"
]
}
}
}
and this is how I build the library:
babel src --out-dir lib --extensions '.js,.jsx' --source-maps inline --watch
in my library I also have peerdep in my package.json
"peerDependency": {
"styled-components": "4.4.1",
"react-dom": "16.8.3",
"react": "16.8.3"
}
Also, if I comment the imported component and I reload I don't see any error, if I remove the comment the page is reloaded with hot reload and I can see the component without error and it works fine....if I reload the page I get the error again
Do you have any sample code or a sample 3rd party package that I could reproduce this with?
This generally means that the package you're importing is using it's own React version and it's not using React as a peerdep.
@timneutkens sounds like a reasonable explanation!
@francescovenica if you are using yarn, try running yarn why react from your project directly. If it returns two instances of React, @timneutkens is right. To converge two or more copies of React, you can try fixing dependencies in your library's package.json or force a single version of React via Yarn's resolutions feature. Using yarn-deduplicate also helps in some cases.
hello, after a lot of tests I found out that as you said it is caused by double instances when linking modules, I have the same problem with styled component but I was thinking that adding this:
'styled-components': path.resolve(__dirname, '.', 'node_modules', 'styled-components'),
'react-dom': path.resolve(__dirname, '.', 'node_modules', 'react-dom'),
'react': path.resolve(__dirname, '.', 'node_modules', 'react'),
and the "peerDependency" would be enough to fix the problem...
I was able to get all working linking my library and then manually remove react/react-dom/styled-component from node_modules of the library, obviously this is only a temp fix....
Later I'll push a sample of the problem but is a very basic mix of:
https://github.com/zeit/next.js/tree/canary/examples/with-styled-components
https://github.com/zeit/next.js/tree/canary/examples/custom-server-express
and a simple library with an index where I export my components
That won't exactly work for all cases as Next.js doesn't bundle node_modules, so it'll be mismatching if other deps use a different version of React too.
This is my sample with just one page/component
https://github.com/francescovenica/nextjs-test
@timneutkens I'm not super expert of webpack and similar, are there any solution about your point?
@francescovenica If you want to separate your ui components from your app I would suggest you to go with monorepo approach. You can check lerna. Then you won't even need to use module transpiler plugin.
Alternatively you can go with yarn workspaces or lerna with yarn workspaces too.
P.S using lerna is not actually the solution of your problem but it makes it easier to handle symlinks between packages in monorepo scenario. If you need for setting up the project hit me up on spectrum https://spectrum.chat/users/enes-tufekci
This happens for me when I yarn link in a component from another repo
React / Nextjs seem to get confused thinking there is 2 versions of react when there isnt.
(if i run npm ls react i cant see any duplicates)
https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react
I have tried to set specific resolutions for react and react-dom but no go - also tried to set a react alias with some nextjs / webpack config but no go :(
Duplicate of #9022
Most helpful comment
This happens for me when I
yarn linkin a component from another repoReact / Nextjs seem to get confused thinking there is 2 versions of react when there isnt.
(if i run
npm ls reacti cant see any duplicates)https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react
I have tried to set specific resolutions for react and react-dom but no go - also tried to set a react alias with some nextjs / webpack config but no go :(