tsdx
tsdx copied to clipboard
"Invalid hook call" error when importing a TSDX library with styled-components
Current Behavior
I'm building a private library with tsdx
and would like to add styled-components
there. When I do it, they work within the tsdx
project but when I import those components in other projects (next.js/CRA
using already styled-components
inside), 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.

Expected behavior
I would like to be able to use those styled-components
exactly like any other react, or plain js function I'm able to use with tsdx
, so they can be reused in my projects.
Especially when the test for those styled-components works and they get rendered correctly inside storybook
.
Suggested solution(s)
Please, provide a concise way to enable tsdx-styled-components
to use styled-components
and export them correctly 🙏.
Additional context
I isolated this problem in a small project and prepared the steps to reproduce it:
-
Create an empty project
npx tsdx create tsdx-styled-components
And uploaded to Github
-
Add styled-components to it and a small component exported in the index
With the second commit I added
styled-components
to the project, they get render correctly instorybook
and test pass correctly for thosestyled-components
components. -
Create a new next.js project and consume the library locally
-
Create a new project with yarn create next-app --example with-typescript next-ts-styled-components-tsdx-host.
-
Then yarn build the
tsdx-styled-components
. -
yarn add ../tsdx-styled-components
innext-ts-styled-components-tsdx-host
(just to use it locally before registering) -
Modify the
pages/index.tsx
file to use the new library:import Link from "next/link"; import { Thing, SimpleStyledH1Application } from "tsdx-styled-components"; import Layout from "../components/Layout"; const IndexPage = () => ( <Layout title="Home | Next.js + TypeScript Example"> <Thing></Thing> {/* This causes the break, because is a styled-component */} <SimpleStyledH1Application /> <h1>Hello Next.js 👋</h1> <p> <Link href="/about"> <a>About</a> </Link> </p> </Layout> ); export default IndexPage;
I'm creating a new project just to verify, but we get the same error in our CRA, next.js projects with
styled-components
configured.SimpleStyledH1Application
causes the error, if you comment it, the page renders correctly.
-
-
Add the workaround described in https://github.com/formium/tsdx/issues/543 doesn't work.
With the third commit,add
styled-components/macro
version and addsbabel-plugin-macros
to.babelrc
as described https://github.com/formium/tsdx/issues/543 & https://github.com/formium/tsdx/pull/644.
Your environment
System:
OS: macOS 11.1
CPU: (16) x64 Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
Memory: 79.52 MB / 32.00 GB
Shell: 5.8 - /bin/zsh
Binaries:
Node: 14.13.1 - /usr/local/bin/node
Yarn: 1.22.10 - /usr/local/bin/yarn
npm: 6.14.8 - /usr/local/bin/npm
Browsers:
Chrome: 87.0.4280.88
Chrome Canary: 89.0.4366.0
Firefox Developer Edition: 83.0
Safari: 14.0.2
Hi @robertovg
Are you using yarn link
or npm link
to link your app with your library?
A similar issue is discussed here: https://github.com/facebook/react/issues/13991
A possible solution with craco
Override create react app configuration if you use create react app scripts.
-
Install
craco
andcraco-alias
.
yarn add -D @craco/craco craco-alias
- Update
craco.config.js
const CracoAlias = require('craco-alias');
// Source: https://github.com/facebook/react/issues/15315#issuecomment-638504372
module.exports = {
plugins: [
{
plugin: CracoAlias,
options: {
source: 'options',
baseUrl: './',
aliases: {
// described at https://github.com/facebook/react/issues/13991
react: './node_modules/react',
'react-dom': './node_modules/react-dom',
'styled-components': './node_modules/styled-components',
},
},
},
],
};
Reference: https://github.com/facebook/react/issues/15315#issuecomment-638504372
Unfortunately, we are using next.js. I added the Craco config both to the host and to the library project, and I'm getting exactly the same problem. Because @zoltan-nz, the idea is to add this override of libraries to the host or library project?
Well, making some reading (https://github.com/vercel/next.js/issues/9022, https://github.com/vercel/next.js/issues/7626) looks like the wrong version of styled-components
, react-dom
, or react
can cause this problem.
If you follow my instructions to create a host project you will see, tsdx compiles correctly the tsx
but only the component without styled-components can be used there, so looks like is related to styled-component
library conflict (but in the example described, I'm using same styled-component
version).
I can upload the host project if this helps and I would really appreciate any further help with it. The idea is to use tsdx
to create a library project to be used in next.js
for our use case.
Thanks again in advance.
We are having the same exact problem using Next.js. The link works fine if we use a webpack alias for CRA, but for Next.js there is no way to make it work.
Did anyone find a solution/fix?
We are having the same exact problem using Next.js. The link works fine if we use a webpack alias for CRA, but for Next.js there is no way to make it work.
Did anyone find a solution/fix?
Good to know someone else is facing the same issue. I would really love to find a solution. I hope someone can put light on it, as otherwise, we can't have libs packages using tsdx.
We are having the same exact problem using Next.js. The link works fine if we use a webpack alias for CRA, but for Next.js there is no way to make it work. Did anyone find a solution/fix?
Good to know someone else is facing the same issue. I would really love to find a solution. I hope someone can put light on it, as otherwise, we can't have libs packages using tsdx.
Same issue here... this really should be addressed, else it's our only blocker to us using tsdx
I was able to fix this by using the solution in #543, which only seems to work if you don't need any other babel plugins?
Sorry @kylepeeler, we tried this solution too and still got the same problem.
Just to allow people to recreate the issue, I just uploaded the host project: https://github.com/robertovg/next-ts-styled-components-tsdx-hosttsdx-styled-components
It will work out of the box, but as soon as we link tsdx-styled-components
or create a symbolic link in the host to the tsdx-styled-components
it won't..
Without that, we don't have any way to test our library in the host project before committing to Github (with this simple way of using as Git URL)
PD: Same behavior also using babel-plugin-styled-components
instead of macro
We found something interesting, maybe someone can explain this a bit more:
We have both projects:
we run the host and it works, and npm ls react
has no conflicts
Then we yarn build
& yarn link
the tsdx-styled-components
and then:
- The project stop running showing our issue.
-
npm ls react
returnsinvalid [email protected] extraneous
The funny thing is the two projects are using exactly the same react version and it's marked in
peer dependencies
.

I hope the source of the problem it's more clear now.
We found a dirty hack to make it work in local finally. As I said, it will work perfectly when the project is running with the default configuration in the projects, but when we want to run the lib project locally and see the changes in the host is when we face the problems.
We realized the problem was with duplication react version, meaning the host project has 2 copies of react, the default one /next-ts-styled-components-tsdx-host/node-modules/react
and /next-ts-styled-components-tsdx-host/node-modules/tsdx-styled-components/node-modules/react
and just deleting the later we get the project working, the problem is if we do that, then we can't successfully build the lib project (needs react).
So our solution finally is what the official React guide suggest:
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.
In our case, having both projects in the same folder, in the tsdx-styled-components (lib project)
we execute npm link ../next-ts-styled-components-tsdx-host/node_modules/react
and makes everything work.
Not sure if there is a better way, but this works.
Running into the same problem here with latest Next.js (10.0.5).
I refer to my package on the same filesystem in package.json
as follows:
"dependencies": {
"next": "10.0.5",
"react": "17.0.1",
"react-dom": "17.0.1",
"my-package-name": "file:../my-package-name"
}
Hey @timosnel , I pretty sure you only need to execute the same solution I posted,
cd my-package-name;
npm link ../your-host/node_modules/react
I hope it works also for you,
I was having the same issue (not with styled-components but with Ant design library) and I am also referencing my lib project on the same filesystem as @timosnel and I fixed it with npm link as @robertovg suggested. Thanks a lot!
I have a question about the production environment - from what I understand the link is created locally only, is that correct? How can I make it work in production if I am referencing my lib package from the same filesystem? @robertovg maybe you can help? Thanks
@robertovg solution worked -- for me I had to pass --legacy-peer-deps
as well:
npm link --legacy-peer-deps ../${HOST_PROJECT}/node_modules/react/
@robertovg's solution worked for me as well, thanks! 🎉
I had a similar problem. My solution was to add a "resolutions
" object to my package.json
(a yarn feature).
"resolutions": {
"react": "^17.0.2"
}
N.B. I'm also using yarn workspaces which could also solve some problems with duplicate react
versions as deps are hoisted to a single node_modules
in the root.

This issue is kind of wired after 2 days of trying to resolve this issue with different suggestions and I was still unable to resolve it, but In my case, I was able to resolve this issue by removing react
from peerDependencies
in my package.json