Closed sehqlr closed 2 years ago
@sehqlr
Before digging too much into this, here is the error that is being reported in your console: https://reactjs.org/docs/error-decoder.html/?invariant=321
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.
None of the errors listed there seems related to react-select. My guess would be that if the beta of Gutenberg is using v17, then it could be possible that all of the references of React aren't being updated to v17 to match.
Would you kindly take a look at your lock file to ensure your project is only importing one version of react and react-dom?
Hey @ebonow, thanks for your question. All of this functionality is implemented in a WP plugin. That plugin's package.json
doesn't mention react
or react-dom
directly; the Component class is being loaded from WP's element package.
Now, I have a webpack noob question: If react-select
depends on react
, does that copy of react get included in a webpack build? Because if it does, that would explain a few things.
@sehqlr did a bit more research on this and did come across the issue you logged on wordpress.
My understanding on the Gutenberg plugin is that it is an abstraction wrapper over React so no other React dependencies are needed or should be imported. In the case of react-select
, React is listed as a peer-dependency
which means that it's not included within the package, but it is still a dependency for react-select to work.
I created a Wordpress account and will likely add on to that support thread you created as it seems to be more related to the handlings of react as opposed to any internal functioning of the library, but before commenting there, thought to ask what version of react-select are you using in this project?
@ebonow You are going above and beyond, and I appreciate your work on helping me on this. The version of react-select is 5.1.0.
Hey, just want to mention that I have noticed the same error in an application I am working on. This is a Python app with React on the front end, and is being installed by another Python/React app using pip. I was able to get rid of the error by downgrading react-select to version 3.2.0. React-select 4.0.0 is the earliest version that this problem appears for us.
I was able to get rid of the error by downgrading react-select to version 3.2.0. React-select 4.0.0 is the earliest version that this problem appears for us.
@weswil07 React-Select v4 was a focus on removing the deprecated lifecycle methods so that it would be compatible with React v17 as well as an update to Emotion v11.
One suspicion I have is that using Emotion to translate the JSX means that there might be some conflict involved there, but I'm too unexperienced with both Emotion and v17 to say so with any confidence.
@ebonow That would make sense. In version 5 the error stems from 'ForwardRef' but in version 4 the error stems from 'EmotionCssPropInternal'.
I recently ran into the same issue in a custom block after updating react-select
from v3 to v5. In my case, the fix turned out to be extremely simple though it took quite some time to arrive there 😅 …
Because Gutenberg provides its own versions of React and ReactDOM, we have to tell third-party libraries about those versions by mapping the package names to the global variables available in the block editor.
In a Webpack setup, that's as simple as adding the mappings to the Webpack configuration's externals
option:
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
},
In this case, react
/react-dom
are the package names (i.e. npm install <package-name>
), and React
/ReactDOM
correspond to the window.React
and window.ReactDOM
global variables.
Credit goes to this article for pointing me in the right direction.
Does that help with your issue @sehqlr?
I recently ran into the same issue in a custom block after updating
react-select
from v3 to v5. In my case, the fix turned out to be extremely simple though it took quite some time to arrive there sweat_smile …Because Gutenberg provides its own versions of React and ReactDOM, we have to tell third-party libraries about those versions by mapping the package names to the global variables available in the block editor.
In a Webpack setup, that's as simple as adding the mappings to the Webpack configuration's
externals
option:externals: { 'react': 'React', 'react-dom': 'ReactDOM', },
In this case,
react
/react-dom
are the package names (i.e.npm install <package-name>
), andReact
/ReactDOM
correspond to thewindow.React
andwindow.ReactDOM
global variables.Credit goes to this article for pointing me in the right direction.
Does that help with your issue @sehqlr?
Thank you @montchr You saved my day.
@montchr solution is the correct way to fix this issue.
I will close this as there being a solution available.
I would request this be reopened. I have the same issue, but a different subset: I use react-select in a component that I use within a Gutenberg, but also on the front-end with a 'regular' React.
Previous versions have worked just fine in tandem with Gutenberg, but trying the latest major updates (4.x, 5.x) gives me tens of 'ForwardRef' / Invalid hook call errors when using the same component in gutenberg. Sidenote: 4.x gives me tens of EmotionCSS errors, rather than forwardref. 3.x works fine for me.
I would request this be reopened. I have the same issue, but a different subset: I use react-select in a component that I use within a Gutenberg, but also on the front-end with a 'regular' React.
Previous versions have worked just fine in tandem with Gutenberg, but trying the latest major updates (4.x, 5.x) gives me tens of 'ForwardRef' / Invalid hook call errors when using the same component in gutenberg. Sidenote: 4.x gives me tens of EmotionCSS errors, rather than forwardref.
@mevanloon I'm also using this as you described. Actually, when we understand the cause of the issue the solution is simple. The error occurs when the react version used by react-select is different from the one in Gutenberg. By providing react and react-dom as externals to the build context, Webpack uses the same react version that was added to the window object by the Gutenberg. As long as Gutenberg and react-select use two different react versions, it will throw errors.
It makes sense to think that, but I don't think differing React versions is the issue here. I'm using React 17.x to build all my components -- components that all get used in the Gutenberg editor, but also on the front-end. Because I use import React from 'react'
in my components, it uses that version for the eventual compiled script -- even in Gutenberg. Gutenberg is also using react version 17.x for the past year. Not to mention that react-select 3.x is working perfectly fine for me, should that be more of an issue, regarding version numbers?
I did have a slight issue with implementing useState
in my components, and had to check if a component was running in a Gutenberg context; if it was, I used wp.element.useState
.
let createState = typeof wp != "undefined" ? wp.element.useState : useState
Anyway, this is probably all because these react components are really not made for Gutenberg (which is it's own little ecosystem), but it's weird to me how many React components do work (like react-select 3.x, for one), even while using their own React object, rather than Gutenberg's.
@mevanloon "I'm using React 17.x to build all my components" this is the issue. In package.json of react-select(even in the latest version and master branch) you can see that react 16 is a dependency. so for react-select, it uses react 16 instead of 17 when you build without providing Gutenberg's react as an external
"I'm using React 17.x to build all my components" this is the issue. In package.json of react-select(even in the latest version and master branch) you can see that react 16 is a dependency. so for react-select, it uses react 16 instead of 17 when you build without providing Gutenberg's react as an external
@RavishaHeshanE25 The repository of react-select
is a so called monorepo, a repository designed to house more than one package. The package.json
file in the root of the project is for the repository, not the package as is. The package has its own package.json
located under packages/react-select/package.json
. There react
is defined as a peerDependency
.
It makes sense to think that, but I don't think differing React versions is the issue here.
@mevanloon There a three causes for this error listed in the explanation in the documentation.
- You might have mismatching versions of React and React DOM.
- You might be breaking the Rules of Hooks.
- You might have more than one copy of React in the same app. React documentation
The last one is what is happening with Gutenberg. Without telling the bundler/compiler otherwise (e.g. externals
in webpack) react-select
and other dependencies inside your bundle will use React exports from a bundled version of React and not from the Gutenberg version.
In general React supports independent versions of itself on one page, but it "[...] breaks if require('react')
resolves differently between the component and the react-dom copy it was rendered with".
@Rall3n sorry. it was a mistake. I saw that when I tried to find the cause for this issue. In my case, there were two react versions as well. 17 from Gutenberg and 16 from the bundle.
Hey y'all,
I'm having a problem with a custom WordPress block that uses react-select and I have come to believe that this is a bug in react-select itself. I know that as a general rule, you shouldn't assume bugs are in the libraries that you use, but I've been at this for weeks and this is the best lead I have right now.
The backstory? My organization contracted with a third party to build out their new website. They are a WP shop, so naturally, they built a WP site. During development, they activated a beta version of Gutenberg (the page editor) to develop against upcoming features, but they left the beta version of Gutenberg on for some reason. (I wasn't there at the time.) Everything worked fine, until we updated WP to 5.8, then all of the sudden the custom blocks stopped working. I accidentally found the workaround of deactivating the beta of Gutenberg, and ever since then I've been working on figuring out what is happening.
Let's get to some concrete details. I'll start with screenshots:
Here is what my local environment looks like before the bug strikes:
The "CPT Archive" component in the center of the screen is the custom block I'm using in my test page, but there are several blocks that break due to this bug.
This next screenshot is production, where the workaround has been applied and everything works as expected:
If you look to the right, you'll see a panel with several controls for the block. This is where react-select is used, under the "Choose up to three posts" text. I'll post the source code for this component below these screenshots.
Here is the final screenshot, where things go wrong...
As soon as you click on the block, when the side panel with the react-select component tries to mount, it completely breaks the custom block. If you look at the console log, there's a mention of the
<ForwardRef>
component erroring out.I can't post the entire codebase here, but I will post two React components. The first one is called PostTypePicker:
The next one is called ResourcePicker:
As you can see in the code, I've added calls to
console.log
. For the particular CPT Archive component, it uses PostTypePicker (the first one). The error happens afterPostTypePicker.render()
is called, but beforePostTypePicker.componentDidMount()
. So, this leads me to believe that the error about<ForwardRef>
is happening withinAsyncSelect.render()
or similar.An additional detail: when the stable version of Gutenberg is enabled, it uses React 16.13.x. When the beta version of Gutenberg is enabled (when the bug triggers) it uses React 17.0.x.
Sorry this turned into a book of a bug report. I'm pretty much stumped on this one, and I'm hoping that it's just something obvious I missed because this particular area is new to me.
Thanks in advance, Sam