Invalid hook call issue solved when configuring with Lerna, SSR and react-redux v7.1.0 (connectAdvanced.js)
While developing KRA framework I got an error of Invalid hook call
. I suppose if you came to this story you got it too.
In my setup essential components to the error are Lerna, react
, react-dom
, redux
and react-redux
specifically of version 7.1.0
.
The actual react
error states:
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://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.
at invariant (/Users/maxim/setup-app-suite/packages/setup-app-templates/templates/react-redux-thunk-router/node_modules/react/cjs/react.development.js:85:0)
at resolveDispatcher (/Users/maxim/setup-app-suite/packages/setup-app-templates/templates/react-redux-thunk-router/node_modules/react/cjs/react.development.js:1470:0)
at useMemo (/Users/maxim/setup-app-suite/packages/setup-app-templates/templates/react-redux-thunk-router/node_modules/react/cjs/react.development.js:1524:0)
at ConnectFunction (/Users/maxim/setup-app-suite/packages/setup-app-templates/templates/react-redux-thunk-router/node_modules/react-redux/es/components/connectAdvanced.js:116:28)
at processChild (/Users/maxim/setup-app-suite/packages/setup-app-ssr/node_modules/react-dom/cjs/react-dom-server.node.development.js:2888:14)
at resolve (/Users/maxim/setup-app-suite/packages/setup-app-ssr/node_modules/react-dom/cjs/react-dom-server.node.development.js:2812:5)
at ReactDOMServerRenderer.render (/Users/maxim/setup-app-suite/packages/setup-app-ssr/node_modules/react-dom/cjs/react-dom-server.node.development.js:3202:22)
at ReactDOMServerRenderer.read (/Users/maxim/setup-app-suite/packages/setup-app-ssr/node_modules/react-dom/cjs/react-dom-server.node.development.js:3161:29)
at Object.renderToString (/Users/maxim/setup-app-suite/packages/setup-app-ssr/node_modules/react-dom/cjs/react-dom-server.node.development.js:3646:27)
at processMethod (/Users/maxim/setup-app-suite/packages/setup-app-ssr/lib/SSRMiddleware.js:70:41)
The issue starts when you upgrade react-redux
from 6.0.1
to 7.1.0
because react-redux
team started utilizing some react-dom
components.
Therefore, when you bundling your SSR code with webpack
it copies both react
and react-dom
to your output file. This is one copy of react
and react-dom
. The other copy is the one you actually require
to execute your ReactDOMServer.renderToString
.
The solution
Instead of bundling both react
and react-dom
with the rest of your SSR code, you need to keep require
statements to include those at the time of execution from the same place you includeReactDOMServer.renderToString
.
To do that you have to configure externals
in your webpack.config.js
to exclude both full react
and react-dom
libraries from the bundle, but leave require('react')
and require('react-dom')
when building code for SSR:
node: false,
target: 'node',
externals: [ 'react', 'react-dom' ],
The actual implementation for my framework is here.
Also, make sure you include your ReactDOMServer.renderToString
from the same place you include your react
and react-dom
.
In my case to renderToString
I rely on one of my dependencies with lerna
configuration. In my setup to ensure the ReactDOMServer
is included from the same place I require
react-dom/server
from node_modules
in the current working directory, the directory where you run your npm start
or node ./index.js
:
const path = require('path');
const ReactDOMServer = require(
path.join(
process.cwd(),
'node_modules',
'react-dom',
'server'
)
);
The actual implementation is here.
Don’t forget to add react
and react-dom
as your dependencies
in package.json
to have both of these libraries in your node_modules
when you executing your project in production.
That’s it. Have a happy coding!
If you like my solution give me some claps and leave your happy comment below :) Thanks!