Since CM mode now runs useEffects' cleanups async. Are we still guaranteed that they'll resolve in order? By that I mean, if a component get's cleanup, re-rendered and cleaned up again. That the first cleanup will resolve, before the second?
ComponentA (1) -> thrown away -> ComponentA (2) -> thrown away. Will that (2) effectively "await" on the (1) to cleanup first.
React will never stack passive effects. If there are pending effects scheduled when React starts an update– we flush the pending effects (synchronously) before continuing with the update.
Let's say we have the following component:
function ExampleComponent(props) {
useEffect(() => {
// This effect runs after every update,
// because there is no dependencies array.
return () => {
// And it returns a cleanup function.
};
});
// Other stuff...
}
Assuming the component above gets mounted, updated, and then unmounted– the overall sequence will be:
If an update was scheduled before React flushed the passive effect, the overall sequence would not change, e.g.
Hope this answers your question.
@bvaughn this needs to go in the docs somewhere :)
I'm not directly working on the docs effort at the moment, but I'll tag @gaearon and @rachelnabors to share the feedback.
Since CM mode now runs useEffects' cleanups async
I'm not sure I understand the premise — cleanups run async in 17 in sync mode too.
I assumed this comment was inspire by our recent timing change for passive destroys after being unmounted. (Maybe that's wrong.) The overall gist of it seemed to be asking though if it was ever possible for effect destroys and creates to be interleaved in an unpredictable way because of the fact that we delay them.
Yes, I just wanted to clarify for @maraisr that this behavior is unrelated to Concurrent Mode (which is mentioned in the issue title).
Firstly thank you @bvaughn!! But my I guess original question still in the air?? I'm more curious, effects are cleaned up async. But still "sync" in the sense that future effects won't get created till previous have cleaned up? But sibling "unrelated" effect cleanups will run async?
Also sorry @gaearon misunderstanding on my part as when the async cleanups were added CM or 17! 😅
As a side note; sorry for being so ambiguous. Articulation is hard!
But my I guess original question still in the air?? I'm more curious, effects are cleaned up async. But still "sync" in the sense that future effects won't get created till previous have cleaned up? But sibling "unrelated" effect cleanups will run async?
Ah, sorry if my example above made things more confusing by being overly simplified 😅
React processes all effects within a root at the same time. (It won't destroy effects for some components but leave others for later.) If a commit rendered 5 components and 3 of them had effects, all 3 of those effects will be run before React starts on another update.
(Layout effects (useLayoutEffect) and passive effects (useEffect) will be run at different times– but all layout effects will run at one time, and all passive effects at another.)
Ah thank you so much! So for my specific usecase:
useEffect(() => {
someGlobalNonReactSetUserFunction({user});
return () => {
someGlobalNonReactSetUserFunction(null);
}
}, [user])
I'm just wanting to confirm that the cleanup that sets the user to null, won't set it to null after the second commits init ran. But as you're saying commits won't commence till all cleanups have finished. Which means yeah, the setting of null won't ever set it to null for a second commits setting.
Gosh im horrible at this articulating thing... Does it come easier with practice? You do it so well!!!
Most helpful comment
Ah, sorry if my example above made things more confusing by being overly simplified 😅
React processes all effects within a root at the same time. (It won't destroy effects for some components but leave others for later.) If a commit rendered 5 components and 3 of them had effects, all 3 of those effects will be run before React starts on another update.
(Layout effects (
useLayoutEffect) and passive effects (useEffect) will be run at different times– but all layout effects will run at one time, and all passive effects at another.)