keystonejs / keystone

The superpowered headless CMS for Node.js β€” built with GraphQL and React
https://keystonejs.com
MIT License
9.17k stars 1.15k forks source link

Launching Next.js with Styled Components throws React Hooks error #2898

Closed nigelwtf closed 4 years ago

nigelwtf commented 4 years ago

Bug report

Describe the bug

When using Next.js and Styled Components and launching Next.js from Keystone, an erroris printed to the stdout:

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've isolated this specifically to launching Next.js from Keystone's dev command, as navigating to the Next.js directory and launching from there doesn't produce an error.

I further tracked the cause of the error to being the 3rd point in the error message: "You might have more than one copy of React in the same app". Following the stack trace, I've found Next.js is using Keystone's version of React.

This is the good news - moving React and ReactDOM to Next's peerDependencies in package.json resolves the issue. This is probably a documentation change IF the maintainers deem this necessary to document in the first place (it's a pretty niche use case). If that is the case, I'd be happy to raise a pull request (with some guidance).

To Reproduce

  1. Install Next.js in a subdirectory
  2. Install and configure @keystonejs/app-next
  3. Install and configure Styled Components following this example https://github.com/zeit/next.js/tree/canary/examples/with-styled-components (Note, most of the implementation is in pages/_document.js and pages/_app.js.
  4. Run yarn dev
  5. Observe the error in the stdout or visit the app in a browser

Expected behaviour

Keystone should successfully boot a Next.js app with Styled Components without producing errors.

System information

tomasztunik commented 4 years ago

Tried to reproduce your issue @nigelwtf and it was working fine for me. Only issue I had was that it failed to preserve server-side generated styles out of the box and recreated them on the client - did not look into it any further just yet. But the app worked fine and I was able to create more styled components or extend the theme just fine.

~Are you sure you did not add any other components yourself and used hooks (useState or any other use*) inside a class based component class YourComponent extends React.Component? Hooks are compatible only with Function Components.~

Read your comment again, seems I did not have any problems with multiple copies of React. Just FYI all package.json additions for the demo to work for me were:

    "next": "^9.3.6",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "styled-components": "^5.1.0"

Also next.js hot reload was working fine, including updates for styled-component styles.

nigelwtf commented 4 years ago

Ah weird - unsure what's going on my end. I'm definitely still able to reproduce it, and it was virtually a new project when I encountered the error (empty next and keystone apps, only changes was adding styled-components).

I'm using the same versions as you've stated - so very confused as to why it can't be reproduced elsewhere πŸ˜“

I'll try do some more sniffing this evening, and will try different package managers and Node versions to see if different results can be produced.

tomasztunik commented 4 years ago

just FYI was using yarn on my end and node v14

MadeByMike commented 4 years ago

@nigelwtf I can't reproduce this either. Any chance you could upload a reproducible example to github or similar?

nigelwtf commented 4 years ago

Hey - sorry for the late reply. Pretty distracted at the moment. I'll have a go at trying to reproduce it again, and if no dice I'll close the issue :)

nigelwtf commented 4 years ago

Aaaaand accidentally hit "Close and comment". Whoops!

nigelwtf commented 4 years ago

Could not reproduce again. Closing 😊

runemadsen commented 4 years ago

I just followed the "Getting Started" guide for setting up a new keystone app, and after using the app-next package with a vanilla Next.js repo, I'm getting the same 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://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.
    at resolveDispatcher (webpack-internal:///../node_modules/react/cjs/react.development.js:1465:13)
    at useContext (webpack-internal:///../node_modules/react/cjs/react.development.js:1473:20)
    at Html (webpack-internal:///../node_modules/next/dist/pages/_document.js:171:29)
    at processChild (/Users/runemadsen/Code/tiaa/tiaa-one-voice/node_modules/react-dom/cjs/react-dom-server.node.development.js:3043:14)
    at resolve (/Users/runemadsen/Code/tiaa/tiaa-one-voice/node_modules/react-dom/cjs/react-dom-server.node.development.js:2960:5)
    at ReactDOMServerRenderer.render (/Users/runemadsen/Code/tiaa/tiaa-one-voice/node_modules/react-dom/cjs/react-dom-server.node.development.js:3435:22)

I'm guessing this is caused by mismatching versions of React between Next.js and Keystone's Admin UI. What is the correct fix for this?

EDIT I fixed this by moving my next dependency to the root package.json, deleting the package.json and node_modules folder in the next app, and running a clean npm i. This means that Next and Keystone will share the same React version (based on the one in the keystone admin UI dependency).