-1

I'm getting this below warning in console when i run he code.

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.

Here is my code:

 const [userDetail, setUserDetail] = React.useState('');
  const personalDetails = (user_id) => {
    axios
    .get(`http://localhost:3001/users/${user_id}`, { withCredentials: true })
    .then((response) => {
      const personalDetails = response.data;
      setUserDetail(response.data);
    })
    .catch((error) => {
      console.log(" error", error);
    });
  };
  React.useEffect(() => {
   if (user_id) {
    personalDetails(user_id);
  }
}, [user_id]);

If I remove useEffect call, this error disappears. What is wrong here?

SreRoR
  • 1,151
  • 1
  • 17
  • 44
  • 1
    Does this answer your question? [React useEffect causing: Can't perform a React state update on an unmounted component](https://stackoverflow.com/questions/54954385/react-useeffect-causing-cant-perform-a-react-state-update-on-an-unmounted-comp) – Naren May 14 '21 at 22:10
  • 1
    Make `useEffect` *wrap* your api call code and not the other way around. – Janez Kuhar May 14 '21 at 22:10
  • 1
    because it is asynchronous and meets the race condition. Read this: https://medium.com/hackernoon/avoiding-race-conditions-when-fetching-data-with-react-hooks-220d6fd0f663 – Vahid Alimohamadi May 14 '21 at 22:54
  • 1
    Also needs to wrap the function with ```useCallback``` hook if you are using it inside the component function. It helps REACT to memorize that and avoid unnecessary re-renders if there's child component(s) which uses that. – Vahid Alimohamadi May 14 '21 at 22:56

1 Answers1

2

This seems to be what's happening:

  1. Your component mounts.
  2. Your effect runs, which begins making an HTTP request.
  3. The component unmounts for whatever reason (the parent component is removing it).
  4. The HTTP request completes, and your callback calls setUserDetail, even though the component has been unmounted.

Another issue is that you're defining the personalDetails outside of the effect where it's used.

I would make two changes:

  1. Move the body of the personalDetails function inside the effect.
  2. If the component unmounts, or user_id is changed, then you don't want to call setUserDetail anymore, so use an aborted variable to keep track of this.
const [userDetail, setUserDetail] = React.useState("");

React.useEffect(() => {
  if (user_id) {
    let aborted = false;

    axios
      .get(`http://localhost:3001/users/${user_id}`, { withCredentials: true })
      .then((response) => {
        const personalDetails = response.data;

        // Don't change state if the component has unmounted or
        // if this effect is outdated
        if (!aborted) {
          setUserDetail(response.data);
        }
      })
      .catch((error) => {
        console.log(" error", error);
      });

    // The function returned here is called if the component unmounts
    // or if the dependency list changes (user_id changes).
    return () => (aborted = true);
  }
}, [user_id]);
Stephen Jennings
  • 12,494
  • 5
  • 47
  • 66
  • Thanks for a detailed description. the warning is disappered now. Thanks a lot for helping me. I'm new to react and i'm in a learning stage.Thanks again – SreRoR May 15 '21 at 11:09