Reputation: 4473
I've got a very simple hook that looks like this:
export const QuickViewCell = props => {
const [hover, setHover] = useState(false)
const handleMouseEvent = () => {
console.log('calling')
setHover(!hover)
}
console.log('hoverState', hover)
return (
<Box onMouseEnter={handleMouseEvent} onMouseLeave={handleMouseEvent}>
<Text size="small">
{String(props.data.name)} this is my custom cell and it is amazing
</Text>
</Box>
)
It works when placed in one part of the project, but doesn't when placed in another. Meaning, the handleMouseEvent
function is always being called, but the component isn't re-rendering with the new state. React and React-Dom are at 16.8.1. I'm not getting any errors. I'm not sure where to look for the bug.
If I change it to a class component using setState
, it works fine, which makes me think I've got an incompatibility issue somewhere, but without an error message, not sure where to look. Or I'm missing something more obvious :)
Anyone experience something like this? Is there a way to determine if there is an incompatibility with another package?
Upvotes: 1
Views: 2393
Reputation: 81136
Based on the following wording in your question:
It works when placed in one part of the project, but doesn't when placed in another.
I assumed that the two places were part of the same build (i.e. same package.json
). If that was the case, it seemed unlikely that it was an incompatibility issue. But the following recent comment:
The code for this component is identical in both cases, it's mainly the packages that are different.
makes it sound like the two cases are part of separate builds. If this is true, then I think the hook-incompatibility theory is reasonable, though I'm not entirely convinced because I would expect a message in the console in that case (but I suspect there are some variations on the multiple-react-copies issue that wouldn't cause a message in the console).
The following page from the documentation has instructions on troubleshooting this:
https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react
On that page you'll find the below instructions for determining whether you have multiple versions of react in play.
You can run
npm ls react-dom
ornpm ls react-native
in your application folder to check which version you’re using. If you find more than one of them, this might also create problems (more on that below).
And then further down:
If you use Node for package management, you can run this check in your project folder:
npm ls react
If this doesn't show any surprises (i.e. just shows one copy of 16.8.1 for both react and react-dom), then I would move forward with assuming there is something other than an incompatibility going on and would want to see the code that uses QuickViewCell
in the problem case.
On a tangential note regarding jayarjo's recommendation to use the "functional update" syntax, I think the more appropriate way to update this hover
state in order to more easily know that it is correct/robust would be to explicitly pass the boolean rather than doing a toggle of whatever the state currently is.
For example:
export const QuickViewCell = props => {
const [hover, setHover] = useState(false)
return (
<Box onMouseEnter={()=>setHover(true)} onMouseLeave={()=>setHover(false)}>
<Text size="small">
{String(props.data.name)} this is my custom cell and it is amazing
</Text>
</Box>
);
}
This makes it easier to be confident that you won't accidentally get in a state where hover is stuck as the opposite of what it should be.
Upvotes: 1
Reputation: 16754
When previous state is used to calculated next one, it is recommended to use functional updates.
So instead of setHover(!hover)
try setHover(hover => !hover)
. That should do.
Upvotes: 0