-
Notifications
You must be signed in to change notification settings - Fork 48.5k
setState hook inside useEffect can cause unavoidable warning Can't perform a React state update #14369
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
Comments
React.useEffect(() => {
let unmounted = false; // new stuff here
const handle = () => {
console.log("SET VISIBLE BEFORE");
if (!unmounted) setVisible(v => false); // new stuff here
console.log("SET VISIBLE AFTER");
};
emitter.on("B", handle);
return () => {
unmounted = true; // new stuff here
console.log("UNSUBSCRIBE");
emitter.off("B", handle);
};
}, []);
React.useEffect(() => {
let unmounted = false; // new stuff here
if (refresh === 1) {
visible.current = false;
if (!unmounted) setRefresh(v => v + 1); // new stuff here
}
const handle = () => {
if (!unmounted) setRefresh(v => v + 1); // new stuff here
};
emitter.on("A", handle);
return () => {
unmounted = true; // new stuff here
emitter.off("A", handle);
};
}); This code (or we can prevent whole function execution based on |
@Voronar I use a manual flag to avoid warnings just like you, too. but I hope that react can improve it internally. Currently, I think use :-) |
the additional tracking using an |
Using |
@swissmanu Post your code (ideally as a runnable CodeSandbox), we can try to help. |
you're totally right @gaearon (it felt very wrong to me too btw ;) ) after some more in depth inspection of my components life cycles using the profiler i was able to dig down to the underlying problem... et voilà: the warning disappeared. thx anyway! |
@swissmanu What was your solution? |
@ryansully a parent component made its child tree unmount because of an async side effect. the code i tried to fix through sorry to not be able to give you a more satisfying answer 😔 |
My temporary un-tested workaround is
In your component
|
What is the difference to just using a flag like let unmounted = false;
React.useEffect(() => () => unmounted = true, []); |
@misantronic the |
Generally a much simpler solution is something like React.useEffect(() => {
let didCancel = false;
// ...
// you can check didCancel
// before running any setState
// ...
return () => {
didCancel = true;
};
}); |
I think |
Perfect solution! Thank you |
@gaearon your workaround does not work when one wants to do an async action outside of
|
Sure, in that case you can keep |
I'm getting this "unmounted component." warning in my app as well. How is a UPDATE-- oh, I get it. It's a listener running from outside the component -- is that correct? |
In #14369 (comment), the variable |
Would it make sense to put a
I just added it and so far it's thrown no errors. |
@VikR0001 The discussion will be more productive if you link to CodeSandbox that reproduces your problem. We can’t guess anything about your code. So your comments mostly create confusion for future readers. However, if you link to the code then they could become helpful. |
@gaearon I don't yet know what would cause a
|
The solution in #14369 (comment) is usually the right one. (Or preferably you'd cancel the async work you're doing.) Note there might also be a legit bug where this warning is unavoidable. I'm tracking that bug in #15057. I'll lock this issue to prevent further confusion. If you have an avoidable warning like this and #14369 (comment) doesn't solve it, file a new issue with CodeSandbox demo. |
This appears fixed with |
BUG
What is the current behavior?
Example: https://codesandbox.io/s/6y1x2zr21n clicking on OK button cause
Warning: Can't perform a React state update on an unmounted component.
The problem that unsubscribe is called during B event
setVisible(v => false);
call, see logs:In our case we have this even without RAF call, but on
transitionend
DOM event.(It's occurred randomly and rare in our codebase as transitionend event should be called exactly at needed time, but example showed what happens)
Seems like it occurred only if you have a
setState
call during useEffect callback likesetRefresh(v => v + 1);
(inside provided code) (after rewriting our codebase to avoid setState calls in useEffect the error has gone)Code
What is the expected behavior?
Do not provide warning if unsubscription is called during "setState" call.
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
React 16.7.0-alpha.2
The text was updated successfully, but these errors were encountered: