Fundamentally broken
Opened this issue · 4 comments
In react strict-mode, hooks are sometimes executed a second time to check if the output is pure & the same (in some weird ass mode where console.log is overridden to hide log side effects).
This is however a fundamental issue with useImmediateEffect implementations, as the immediate effect is run again in this mode, and almost always has side effects.
Not sure this can be fixed. Leaving this here as a warning for others as it took me half a day to figure out what was going on.
This weird mode can be detected with import('react').__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner.current.mode === 9
btw, that could be a very hacky way to make this hook work as intended still.
This is not an issue with useImmediateEffect
, it's just the way strict mode works. useEffect
and useLayoutEffect
behave the same way.
I'm curious what you are seeing and what your use case is.
Thanks for your response, but I'm afraid you're misunderstanding.
React in strict-mode sometimes does an extra render pass without running side-effects (so not doing things declared in useEffect
or useLayoutEffect
), and also not rendering children. But since the render() logic is called, effects with useImmediateEffect
are executed. See also this comment for more info.
Our use case (otherwise irrelevant) is simply subscribing in some observable data pattern, then doing setState in the onChange callback. We would see that these subscriptions were leaking (and would get a lot of Can't perform a React state update on an unmounted component
messages in development subsequently). It was extra confusing because console.log
s weren't shown in this mode. Honestly whoever in the React team thought this was a good idea...
I had better success if I changed useEffect to useLayoutEffect on this line:
I guess the problem (for me) was that the component got unmounted so quickly so the effect never ran, so the cleanup function never got registered. With useLayoutEffect if works better.