If you are developing a React application, you might encounter the following error message in your browser console:
Uncaught Error: Minified React error #185; visit https://reactjs.org/docs/error-decoder.html?invariant=185 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
This error means that you are trying to update a component that is not mounted on the DOM. This can happen if you use a `setState` or a `useEffect` hook in a component that is conditionally rendered or unmounted by another component. For example, you might have a modal component that is rendered only when a button is clicked, and you try to update its state after it is closed.
To fix this error, you need to make sure that you only update the state of a component that is mounted on the DOM. There are a few ways to do this, depending on your use case:
- Use a flag variable to check if the component is mounted before calling `setState` or `useEffect`. For example, you can use a `useRef` hook to store a boolean value that indicates if the component is mounted, and update it in the `useEffect` hook with an empty dependency array. Then, you can use this value to conditionally update the state of the component. Here is an example:
import React, { useState, useEffect, useRef } from "react"; function Modal({ isOpen, onClose }) { const [count, setCount] = useState(0); const isMounted = useRef(false); useEffect(() => { // Set the flag to true when the component mounts isMounted.current = true; // Set the flag to false when the component unmounts return () => { isMounted.current = false; }; }, []); useEffect(() => { // Only update the state if the component is mounted if (isMounted.current) { setCount((prevCount) => prevCount + 1); } }, [isOpen]); return ( <div className="modal"> <h1>Modal</h1> <p>Count: {count}</p> <button onClick={onClose}>Close</button> </div> ); }
- Use a cleanup function in the `useEffect` hook to cancel any pending state updates when the component unmounts. For example, you can use an abort controller to abort any fetch requests that might update the state of the component after it is unmounted. Here is an example:
import React, { useState, useEffect } from "react"; function Data({ url }) { const [data, setData] = useState(null); useEffect(() => { // Create an abort controller to cancel the fetch request const controller = new AbortController(); const signal = controller.signal; // Fetch the data from the url fetch(url, { signal }) .then((response) => response.json()) .then((data) => { // Only update the state if the component is mounted if (!signal.aborted) { setData(data); } }) .catch((error) => { // Handle the error console.error(error); }); // Return a cleanup function that aborts the fetch request return () => { controller.abort(); }; }, [url]); return ( <div className="data"> <h1>Data</h1> {data ? ( <pre>{JSON.stringify(data, null, 2)}</pre> ) : ( <p>Loading...</p> )} </div> ); }
- Use a custom hook that handles the mounting and unmounting logic for you. For example, you can use the `useIsMounted` hook from this article: https://www.benmvp.com/blog/handling-async-react-component-effects-after-unmount/. This hook returns a function that you can call to check if the component is mounted before updating its state. Here is an example:
import React, { useState, useEffect } from "react"; import { useIsMounted } from "./useIsMounted"; function Counter() { const [count, setCount] = useState(0); const isMounted = useIsMounted(); useEffect(() => { // Simulate an async operation that updates the state after 3 seconds setTimeout(() => { // Only update the state if the component is mounted if (isMounted()) { setCount((prevCount) => prevCount + 1); } }, 3000); }, []); return ( <div className="counter"> <h1>Counter</h1> <p>Count: {count}</p> </div> ); }
I hope this blog post helped you understand how to resolve the Uncaught Error: Minified React error #185.