Add a status argument to the useEffect/useLayoutEffect callback.
Basic example
;
Motivation
When ever we use an effect with a state update inside an async callback (or after an await) we probably want to check that we are not trying to update an unmounted component or worse, we are in a race condition and updating the state with the wrong data.
This is fairly simple to achieve using a boolean and a closure:
;
But doing that in each effect, every time we are dealing with a state update in an async operation can become tedious. It would be nice if effects would provide this info so users won't have to create booleans and return a function that flip them every time.
Another possible issue, is the fact that some developers doesn't think about cleanups this way, cleaning up is usually done to explicit APIs like subscribers or some well known browser APIs such as setTimeout and setInterval, but some (or most) developers don't think about effect cycles and async updates while writing the code, until they hit a bug. Explicitly passing a status to effects callbacks can help developers think and "remember" that their async operation and updates should properly handled when there is a change.
Detailed design
- The effect callback can accept an object parameter.
- useEffect/useLayoutEffect will pass an object with a boolean property
aborted(not sure about this name at all) asfalse. - On cleanup, useEffect/useLayoutEffect will mutate the passed object and will set
abortedtotrue.
Drawbacks
- I'm not sure what is the implementation cost, both in term of code size and complexity.
- This can be implemented in user-land (but can get either tedious or "ugly" API).
- Might be a small extra "thing" to teach developers.
- Might be considered "magic" or "black box" by some developers.
Alternatives
There might be a "user-land" solution by wrapping useEffect/useLayoutEffect:
And the usage:
;
Unresolved questions
Not sure about the name aborted, it is too related to specific use cases. Maybe something like isCleaned or something similar.