react: Bug: React.StrictMode causes AbortController to cancel
React version: 18.2
Steps To Reproduce
- import a hook that uses AbortController
- Without React.StrictMode the abort controller aborted = false
- With React.StrictMode the abort controller gets set to aborted = true
const useAbortController = (abortControllerProp, shouldAutoRestart = false) => {
const abortController = useRef(abortControllerProp || initAbortController());
useEffect(() => {
if (shouldAutoRestart && abortController.current.signal.aborted) {
abortController.current = initAbortController();
}
}, [abortController.current.signal.aborted, shouldAutoRestart]);
useEffect(() => () => abortController.current.abort(), []);
return abortController.current;
};
The current behavior
The “echoed” rendering of the component causes the the controller to go from aborted false -> true.
The expected behavior
I’m not sure if this is inherent to what react tests for in this mode, or something that can be expected to work.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 15
I have the same issue with a single abort controller being called to abort multiple API calls. Here’s my example code for easier reproduction:
According to API docs, this code should not have any issues and technically fetch, abort, then fetch again the data from API. But the issue is that the aborted API call throws CancelledError even on the second attempt:
Solution to this particular issue is to create abort controller in effect, and do not use useMemo or useState for it.
But still, I consider this issue a bug, because it should not matter if we use AbortController or something else, the problem with useEffect getting wrong object still exists.
I made a custom hook for the AbortController that seems to work in strict mode
The issue here is that your effect’s code isn’t symmetric. You shouldn’t implement cleanup in a separate effect — the effect that creates the controller should be the same one that destroys. Then an extra cycle wouldn’t break your code.
@EdmundsEcho the recommended approach it to just let it happen and make sure it works correctly