DEV Community

Cover image for React 18 removes “Can't perform a React state update on an unmounted component” warning ⚠
Alaa Mohammad
Alaa Mohammad

Posted on • Updated on

React 18 removes “Can't perform a React state update on an unmounted component” warning ⚠

Everyone who has worked in React for a while remembers a lot of guidelines to avoiding the following warning: ⚠

Warning: 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

💡This warning arises in case of an asynchronous operation tries to update a state of an unmounted component.
To hide this warning we used to apply the following solution by checking if component is mounted or not:

  const isMountedRef = useRef(false)

  useEffect(() => {
    isMountedRef.current = true
    const getUserData = async () => {
      const response = await fetch(
        `https://jsonplaceholder.typicode.com/users/${userId}`
      );
      const data = (await response.json()) as UserInfo;
      if (isMountedRef.current) {
        if (data.name) {
          setUserInfo(data);
        } else setUserInfo(null);
      }
    };
    getUserData();
    return () => {
        isMountedRef.current = false
    };
  }, [userId]);
Enter fullscreen mode Exit fullscreen mode

🌟However, since React 18, the React team has removed this warning (when calling setState on an unmounted component), because this warning is widely misunderstood and is can be misleading. So, you can write your useEffect as follows without fear of memory leak, also, since you are using Promises then the previous warning will not be triggered.

  useEffect(() => {
    const getUserData = async () => {
      const response = await fetch(
        `https://jsonplaceholder.typicode.com/users/${userId}`
      );
      const data = (await response.json()) as UserInfo;
        if (data.name) {
          setUserInfo(data);
        } else setUserInfo(null);
    };
    getUserData();
  }, [userId]);
Enter fullscreen mode Exit fullscreen mode

👉On the other hand, avoiding adding isMounted checking will be relevant for upcoming React versions because there may be some features that preserve the DOM and its state even when the component is not mounted (not visible).

💻To verify this situation from yourside, you can use the following code which simulate the situation in which component was unmounted by the time the response was received.

import React, { useEffect, useState } from "react";


type UserInfo=Record<string, any>;

export const AppContainer = () => {
  const [show, setShow] = useState(true);
  useEffect(() => {
    /// UserDashboard will unmount after 3000 milliseconds
    const intervalId = setTimeout(() => setShow(false), 3000);
    return () => {
      clearTimeout(intervalId);
    };
  }, []);
  return show ? <UserDashboard /> : <div>no items to show</div>;
};

const UserDashboard = () => {
  const [userInfo, setUserInfo] = useState<UserInfo | null>(null);
  useEffect(() => {
    const getUserData = async () => {
      const response = await fetch(
        `https://jsonplaceholder.typicode.com/users/1`
      );
      const data = (await response.json()) as UserInfo;
      if (data.name) {
        setUserInfo(data);
      } else setUserInfo(null);
    };
    /// The response will take at least 4000 milliseconds
    const intervalId = setTimeout(getUserData, 4000);
    // return ()=>{clearTimeout(intervalId)}
  }, []);

  return userInfo ? (
    <UserCard userInfo={userInfo} />
  ) : (
    <div className="not-found">No user found, Check user Id</div>
  );
};

type UserCardProps={userInfo: UserInfo}

const UserCard = ({ userInfo }: UserCardProps) => {
  return (
    <div>
      id:{userInfo?.id}
      <br />
      Name:{userInfo?.name}
      <br />
      Address:
      {`${userInfo?.address?.city} ${userInfo?.address?.zipcode}, ${userInfo?.address?.street}`}
    </div>
  );
};

export default UserDashboard;
Enter fullscreen mode Exit fullscreen mode

You will have no warnings in your console.

Test the code

Top comments (1)

Collapse
 
sona21 profile image
Sona1

Thanks for sharing 🤠