Loading...

Can’t perform a react state update on an unmounted component: How to fix React error?

Can’t perform a react state update on an unmounted component: How to fix React error?

Frontend technology has improved tremendously in the last ten years. It is now just as simple to construct a front-end web application as it was previously. Today, there are several front-end frameworks, and libraries exist. Each framework has its own rules for how we should do things. Specific code pattern violations may damage the functionality of the frontend application or affect performance, resulting in limited accessibility. The React library also defines some set of rules and patterns that we must follow in order for our application to work correctly. Violating certain rules results in many errors, the most common error being: “Can’t perform a react state update on an unmounted component.”

In this article, we will learn why the error: “Can’t perform a react state update on an unmounted component” occurs during state updates in React and what are various ways to resolve it. Following this blog will also teach you about some important React concepts. These concepts will benefit you while dealing with these types of day-to-day errors and warnings.

What does the error: “Can’t perform a react state update on an unmounted component” signify?

The error: “Can’t perform a react state update on an unmounted component” tells us that we are trying to modify a component’s state after the component is unmounted. In simple words, React has removed the component from the VDOM (Virtual DOM) and from the real DOM, and still, we are trying to change its state. Since the component is unmounted or not present in the DOM tree, we cannot change its state variables.

What are the possible reasons for ‘Can’t perform a react state update’ warning to appear?

If you notice, you can see that it’s actually not an error but a warning. This is just to warn you that there may be a memory leak inside the application. A few reasons that this warning might appear are:

  1. We make an API call to fetch some resources from the server. Before the API call finishes, React unmounts the component (may be due to the user closing the modal or navigating to a different page). After the API call is finished, we try to update the state, but since the component is not present in the DOM, we get a warning.
  2. We are using setTimeout or setInterval functions to update the component state after some time. Before updating the component state, if React unmounts the component, we get a warning since the setTimeout or setInterval functions will try to update the component state after a few moments.

Before moving on to the resolution of this error, let us take a look at some basic React terminologies and concepts to understand the root cause of the error better.

What is DOM?

DOM stands for Document Object Model. It represents the HTML page as a tree of nodes. The document is the root node, while the child nodes make up the subtree. The DOM interface allows us to add, modify, or remove objects from the document. The browser rerenders the UI whenever the DOM changes. To update the DOM, the browser provides the document object. It contains the tree representation of the HTML page. To access a node from the DOM tree, we use various methods present inside the document object.

What is Virtual DOM?

The virtual DOM (or VDOM) is a simulated version of the real DOM. It is an object designed to seem like the true DOM. The virtual DOM is less costly to construct than the real DOM since it does not write to the screen. It exists as an object inside the memory rather than an HTML document. There are different implementations for a virtual DOM available such as Snabdom, Million, etc. However, React uses its own implementation of a Virtual DOM.

How does React handle the DOM?

React does not make changes to the browser’s DOM directly. Instead, it uses a Virtual DOM. The usage of Virtual DOM is what makes React so fast. React also combines a reconciliation algorithm to improve its performance and efficiency.

What is meant by mounting?

We provide React with a root node to which React will render our whole application. Further, we create components written in JSX. React recursively transforms the JSX into an object representing a node in the Virtual DOM tree. This way, a whole Virtual DOM tree is created. Now, this Virtual DOM exists only in memory, so we cannot see its content in the browser. To view the contents in the browser, we must create DOM nodes corresponding to the Virtual DOM inside the real DOM. Creating DOM nodes corresponding to Virtual DOM nodes is known as mounting.

During the mounting, React adds a component that exists in the form of a Virtual DOM node in memory to the browser DOM. Due to mounting, we are able to see the component on the screen. Also, if we are using a class-based component, we can run some side effects in the event of a component mount using the componentDidMount() method, and if we are using a functional component, we can use the useEffect() hook.

What is meant by unmounting?

Mounting is the process of adding a component that exists in the form of a Virtual DOM node in memory to the browser DOM. Similarly, unmounting is the process is removing a component from the browser. During unmounting of a component, React removes the DOM node, as well as its child nodes, from the browser DOM and the Virtual DOM. As with mount, we can run side effects on component unmount using the componentWillUnmount() method for class-based components or the useEffect() hook for functional components.

Why can the state not be updated after the component unmounts?

One should not update the state of an unmounted component as it leads to a memory leak. React, before updating the state of the component, doesn’t check if the component is still mounted. So, it’s the responsibility of the developer to take care of this issue. Also, “Can’t perform a react state update on an unmounted component” is not an error but a warning. In programming, we don’t care much about warnings, but we should, as these can be a sign of a memory leak which may degrade the performance of the application.

How to fix the error: “Can’t perform a react state update on an unmounted component”?

To fix the error (or warning), we must check, before every state update, whether the component is mounted. If the component is mounted, we will move ahead and update the state; if not, we won’t update the state. To do this, we can follow two methods:

  1. Move the state to a higher component in the hierarchy or to a root component.
  2. For mounted or unmounted components, use the useRef() React hook to maintain the value of true or false.
  3. Create a custom hook to return true if the component is mounted and false if the component is unmounted.

Fix-1: Moving the state to a higher component in the hierarchy

If a component has some state and is modified even after React has unmounted the component, we will get the warning for sure. But, if we move the state and its logic to a higher component in the hierarchy, then updating the state even after the component unmounts won’t give any warning because the state is not local to the component that was unmounted.

Therefore, to solve the error (or warning), we can move the state to a higher component in the hierarchy, and then pass it on to the child component like this:

function App() { const [state, setState] = useState(); return ( <div> <h1>How to fix React state update error</h1> <Child state={state} setState={setState} /> </div> ); } function Child(props) { const { state, setState } = props; return ( ... ) }
Code language: JavaScript (javascript)

Fix-2: Check if React has unmounted the component using the useRef React hook

Another way to solve the issue is that we don’t try to update the state if the component is unmounted. To do so, we must know if the component is mounted or not. We use the useRef() React hook to create a mutable object that maintains its value over the component lifecycle without triggering any rerenders. You may think why not make use of the useState() React hook? Updating the state generated by the useState() React hook was the root cause of the error. If we use the useState() React hook to store the value of mount or unmount, the situation will worsen.

To solve the error (or warning), create a mutable object isComponentMounted using the useRef() hook. The isComponentMounted.current is mutable and its value is maintained during the component’s lifecycle. Now using the useEffect() lifecycle hook, we set the value of isComponentMounted.current to true. Then we create a cleanup function that runs when the component unmounts. The cleanup function will set the value of isComponentMounted.current to false. Also, we keep an empty dependency array as we want it to run on the initial render and unmount only and not on updates.

Let’s write the code to understand the process better.

const isComponentMounted = useRef(); useEffect(function () { isComponentMounted.current = true; return function () { isComponentMounted.current = false; }; }, []);
Code language: JavaScript (javascript)

Now, every time you try to update the state, make sure to check if the component is mounted or not using the isComponentMounted.current object.

if (isComponentMounted.current) { setState(...); }
Code language: JavaScript (javascript)

Fix-3: Create a custom React hook to keep a check if React has unmounted the component

We can create a custom React hook to wrap up the whole code to check if the component is mounted or unmounted. This way, rather than writing the logic for every component, we can simply use the custom hook and our code looks cleaner and easier to read. Additionally, Hooks will be more efficient with future React updates. Components could be folded before compilation, for example.

Let us implement a custom React hook for checking if the component is mounted or unmounted. (Please note that the React hook must start with the use keyword).

function useIsComponentMounted() { const isComponentMounted = useRef(false); useEffect(() => { isComponentMounted.current = true; return () => { isComponentMounted.current = false; }; }, []); return isComponentMounted; }
Code language: JavaScript (javascript)

Our hook doesn’t take any arguments and returns a boolean value representing whether React has unmounted the component. The logic we wrote inside the custom hook is the same logic we applied in the second fix to remove the error (or warning).

We may import our custom React hook, and use it inside any component as follows.

const isComponentMounted = useIsComponentMounted();
Code language: JavaScript (javascript)

The isComponentMounted variable will then be used as a check before updating any state inside the component.

if (isComponentMounted.current) { setState(...); }
Code language: JavaScript (javascript)

Conclusion

The React library defines some set of rules and patterns that we must follow in order for our application to work correctly. Violating certain rules results in many errors, one of the most common being: “Can’t perform a react state update on an unmounted component”. The error tells us that React has removed the component from the VDOM (Virtual DOM) and from the real DOM, and still, we are trying to change its state. To fix the error (or warning), we must check, before every state update, if the component is mounted or not. We can do this using three ways:

  1. Move the state to a higher component in the hierarchy or to a root component.
  2. For mounted or unmounted components, use the useRef() React hook to maintain the value of true or false.
  3. Create a custom hook to return true if the component is mounted, and false if the component is unmounted.

Each fix has its own advantages and disadvantages, but, if the purpose is just to mitigate the error (or warning), all three works out great.

To learn more about React internals or how React works under the hook, you can follow the following article from Codedamn:

React Internals Explained – How React works under the hood?

This article hopefully provided you with some new information. Share it with your friends if you enjoyed it. Also, please provide your feedback in the comments section.

Thank you so much for reading 😄

Sharing is caring

Did you like what Varun Tiwari wrote? Thank them for their work by sharing it on social media.

0/10000

No comments so far