-
Notifications
You must be signed in to change notification settings - Fork 47.1k
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
Document that setState() callback is not guaranteed to be called if component unmounts #6320
Comments
Could it be that you were calling react/src/renderers/shared/reconciler/ReactUpdateQueue.js Lines 140 to 144 in 1e81561
|
The issue I was referring to is #1740 and apparently it was fixed. Would be great to verify. If you can do that, and/or provide a test case reproducing the issue, that would be hugely helpful. |
I'm sure that the state is not changed from The setting in my project is a bit complicated: there are two components passed to the react-router Routes, and one of them has some children. For each of these children a function is saved that, when called, calls I traced this down to the I will try to simplify the example down and post a link to jsFiddle. |
Ok, so this turned out to be a lot more complicated than I thought... here's the demo: https://jsfiddle.net/fatfisz/vLv6k3xL. I will try to describe this here too: In my example there are 3 components: Container, A, and B. B is contained in A, and A is contained in Container. Depending on its state, Container will render A with or without B. First we start with all components rendered. Then something cases the state of Container to change so that it will render A without B. But then the update of A is prevented because of the Then the callback for this update (in Container) fires and ruins everything. The update of A is forced (or its state is changed and After those changes are batched, first the A component re-renders and finaly B is unmounted. This causes the callbacks registered in B to be cleared out, and so the callback is lost forever. The conclusion seems to be that if the callback passed to Sorry for the complicated example :) |
Thanks for working it out. I realize now that I read your description without paying enough attention.
IMO this is expected behavior: @spicyj Is my interpretation correct? |
I also agree that this should be expected, sorry if I was being unclear. This still leaves the
|
Oh, and let's not forget about callbacks for |
Yes, I think that the setState callback fires after the rerender (just after componentDidUpdate) and shouldn't fire if the component unmounts first. |
This doesn't seem like a common confusion so I'm not sure it's worth making the language more complex there. The docs now say:
If you follow the tip of using Still, if you see an elegant way to phrase it without making the sentence very complicated, please feel free to send a PR! Thanks. |
I run into the same behaviour and I think the docs could elaborate on it a little bit more. In my specific case, I was setting up a subscription in I guess the docs could mention that references/ids of any side-effects should not be kept in the state. |
I'm only realizing this now as well. I don't think that the recommendation to use |
Currently the only info I could find about the
callback
argument of thesetState
method is this:I've been working on a small tool that relies on the callbacks being called, and I found out that in some cases that never happened: the state was set, the callback was pushed into the queue, then the component was unmounted and the callback was lost and never called.
Now, I don't say that I can't infer the possibility of such scenario from the description above, but an info about when exactly can such callback be considered lost would be helpful. My findings suggest that
componentWillUnmount
is the right place, but I'd be more confident with some assurance from the creators of React :)Also this description suggests that when
shouldComponentUpdate
returnsfalse
(so the component is not re-rendered), the callback will not be called - which is not the case, as the callback still gets called.I'm using React 0.14.7.
The text was updated successfully, but these errors were encountered: