An Interest In:
Web News this Week
- April 21, 2024
- April 20, 2024
- April 19, 2024
- April 18, 2024
- April 17, 2024
- April 16, 2024
- April 15, 2024
An elegant solution for memory leaks in React
Cover image from Valentin Petkov from Unsplash
An elegant solution for memory leaks in React
When working with asynchronous calls, for example API calls, you might have encountered this error :
Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
A GIF is worth a thousand words ...
This is a small page that simulates some asynchronous logic on load, and then updates the view accordingly. Here, I unmount the component before the async work has been finished, and trigger the Error. (I took this example from this StackOverFlow post)
This is caused by this code :
function Example() { const [text, setText] = useState("waiting..."); useEffect(() => { simulateSlowNetworkRequest().then(() => { setText("done!"); // what if the component is no longer mounted ? // => Warning: Can't perform a React state update on an unmounted component. }); }, []); return <h2>{text}</h2>;}
When running into that issue, I found multiple solutions, the most used one seems to be this one :
function OtherExample() { const [text, setText] = useState("waiting..."); useEffect(() => { let isMounted = true; // simulateSlowNetworkRequest().then(() => { if (!isMounted) { // setText("done!"); // no more error } }); return () => { isMounted = false; // }; }, []); return <h2>{text}</h2>;}
But it requires you to add quite a lot of stuff into your component, having to deal with that isMounted
variable all over the place ...
There are other interesting solutions, like making your Promises cancellable :
Cancel Properly HTTP Requests in React Hooks and avoid Memory Leaks
Victor de la Fouchardire Jul 29 3 min read
You told me there would be an elegant solution !
I wasn't lying! The solution I came up with is a very simple hook. It works just like React's useState, but it basically checks if the component is mounted before updating the state !
Here is an example of the refactored code :
function OtherExample() { const [text, setText] = useStateIfMounted("waiting..."); // React.useEffect(() => { simulateSlowNetworkRequest().then(() => { setText("done!"); // no more error }); }, [setText]); return <h2>{text}</h2>;}
Here is the CodeSandBox if you wanna play around !
TLDR
Use useStateIfMounted hook, that will only update the state if your component is mounted !
I hope this might be helpful, feel free to reach me out in any case !
Original Link: https://dev.to/nans/an-elegant-solution-for-memory-leaks-in-react-1hol
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To