How to fix error: Can't perform a React state update on an unmounted component
One error that React developers frequently run into is
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.
It's important to fix this error because it can lead to memory leaks and other performance issues in your React application. In this article, we will discuss what causes this error and how to fix it.
Why "Can't perform a React state update on an unmounted component" is triggered ?
This error occurs when a component's state is updated after the component has been unmounted. The problem arises when there's an asynchronous operation that tries to update the state of an unmounted component.
"An unmounted component is a component that no longer exists in the user interface or DOM."
To put it simply, React checks if the component is no longer a part of the DOM then the state updates of that unmounted component are ignored and thereby preventing the waste of resources.
Consider the example below, where we make an API call on load of the component and route the user to login page if he/she is not authorised. However, we also update the user state variable using setUser(userDetails) after routing and this can result in "Can't perform a React state update on an unmounted component" error if userDetails.isAuthorised is false.
import React, { useState, useEffect } from "react"; import { useHistory } from "react-router-dom"; const Example = () => { const history = useHistory(); const [user, setUser] = useState({ name: "" }); useEffect(() => { const getDetails = async () => { const userDetails = await getUserDetails(); // making an API call if (!userDetails?.isAuthorised) { history.push("/login"); // sending user to login page if not authorised } setUser(userDetails); }; getDetails(); }, []); return ( <div> <h2>hello {user?.name}</h2> </div> ); }; export default Example;
Ways to fix the "Can't perform a React state update on an unmounted component" error
This error can be avoided by cancelling subscriptions which is also indicated in the error message.
-
Update state before unmounting the component
One of the most common approaches is to make sure all the state updates are aligned before unmounting the component. Like this as in above example, set the user details before routing
useEffect(() => { const getDetails = async () => { const userDetails = await getUserDetails(); // making an API call setUser(userDetails); // state update if (!userDetails?.isAuthorised) { history.push("/login"); // sending user to login page if not authorised } }; getDetails(); }, []);
-
Cancel any pending asynchronous processes
Another way is to write a useEffect cleanup method to cancel all subscriptions and asynchronous processes. Like this:
useEffect(() => { // xyz logic // at the end, return a cleanup method return () => {}; }, []);
-
Check if component is mounted:
Consider the example below, where we create a variable isMounted to keep track of whether the component is still mounted. And read isMounted before making updates to the state. In the cleanup function of useEffect, we set isMounted to false, which tells the interval to stop updating the state when the component is unmounted.
useEffect(() => { let isMounted = true; const interval = setInterval(() => { if (isMounted) { setTimer(seconds + 1); } }, 1000); return () => { isMounted = false; clearInterval(interval); }; }, [seconds]);