Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Invalid hook call" error when importing a TSDX library with styled-components #950

Open
robertovg opened this issue Dec 24, 2020 · 17 comments
Labels
kind: support Asking for support with something or a specific use case scope: upstream Issue in upstream dependency solution: out-of-scope This is out of scope for this project

Comments

@robertovg
Copy link

robertovg commented Dec 24, 2020

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.

Screen Shot 2020-12-24 at 4 43 56 PM

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:

  1. Create an empty project

    npx tsdx create tsdx-styled-components

    And uploaded to Github

  2. 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 in storybook and test pass correctly for those styled-components components.

  3. 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 in next-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.

  4. Add the workaround described in Doesn't play well with babel-plugin-styled-components -- plugin order matters #543 doesn't work.

    With the third commit,add styled-components/macro version and adds babel-plugin-macros to .babelrc as described Doesn't play well with babel-plugin-styled-components -- plugin order matters #543 & (fix): change plugin order to make styled-components/macro work #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
@agilgur5 agilgur5 changed the title Use styled-components doesn't work even with the solution described in https://github.com/formium/tsdx/issues/543 "Invalid hook call" error when importing a TSDX library with styled-components Dec 24, 2020
@zoltan-nz
Copy link

Hi @robertovg

Are you using yarn link or npm link to link your app with your library?

A similar issue is discussed here: facebook/react#13991

A possible solution with craco

Override create react app configuration if you use create react app scripts.

  • Craco

  • Install craco and craco-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: facebook/react#15315 (comment)

@robertovg
Copy link
Author

robertovg commented Jan 4, 2021

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 (vercel/next.js#9022, vercel/next.js#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.

@federico-qadra
Copy link

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?

@robertovg
Copy link
Author

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.

@agilgur5 agilgur5 added kind: support Asking for support with something or a specific use case scope: upstream Issue in upstream dependency solution: out-of-scope This is out of scope for this project labels Jan 10, 2021
@kylepeeler
Copy link

kylepeeler commented Jan 11, 2021

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

@kylepeeler
Copy link

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?

@robertovg
Copy link
Author

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

@robertovg
Copy link
Author

robertovg commented Jan 13, 2021

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 returns invalid react@17.0.1 extraneous

The funny thing is the two projects are using exactly the same react version and it's marked in peer dependencies.

Screen Shot 2021-01-13 at 4 31 32 PM

I hope the source of the problem it's more clear now.

@robertovg
Copy link
Author

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.

@timosnel
Copy link

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"
}

@robertovg
Copy link
Author

robertovg commented Jan 25, 2021

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,

@plotka
Copy link

plotka commented Jan 26, 2021

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

@ilovett
Copy link

ilovett commented Feb 10, 2021

@robertovg solution worked -- for me I had to pass --legacy-peer-deps as well:

npm link --legacy-peer-deps ../${HOST_PROJECT}/node_modules/react/

@joshfarrant
Copy link

@robertovg's solution worked for me as well, thanks! 🎉

@OliverDudgeon
Copy link

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.

@gauravverma029
Copy link

gauravverma029 commented May 17, 2021

Screen Shot 2021-05-17 at 11 30 58

Getting error with using next js latest version.what is final hack please share. i am using yarn workspace

@webcodedsoft
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: support Asking for support with something or a specific use case scope: upstream Issue in upstream dependency solution: out-of-scope This is out of scope for this project
Projects
None yet
Development

No branches or pull requests