Gabriel Geelario
Gabriel Geelario

Reputation: 237

How to stop useEffect memory leak in react hook

I am using useEffect hook to fetch data from the server and these data are passed to a list, when I Signup I am getting a warning like below

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.

const getUserData = () => {
  axios.get(`${API_URL}`).then((res) => {
    if (res.data) {
      setUserData(res.data);
    }
  });
};

useEffect(() => {
  getUserData();
}, []);

const logout = () => {
  signout(() => {
    history.push('/signin');
  });
};

return (
  <div>
    <button onClick={() => logout()}>Sign out </button>
  </div>
);

Upvotes: 0

Views: 401

Answers (1)

Mario Petrovic
Mario Petrovic

Reputation: 8332

This happens when your component gets destroyed some of the code left to be executed is done after that destroying. In your case that is callback for API call setUserData(res.data);

Since you are using Axios for your http calls I would suggest to use cancel token to cancel API call on component destroy.

Generate cancel token from axios, pass it to the method getUserData and provide it to axios call. For that useEffect return method that will be executed when component destroys (and there cancel that code, thus cancelling that callback with state set):

const getUserData = (cancelToken) => {
  axios.get(`${API_URL}`, {cancelToken: cancelToken.token}).then((res) => {
    if (res.data) {
      setUserData(res.data);
    }
  });
};

useEffect(() => {
  const cancelToken = axios.CancelToken.source();
  getUserData(cancelToken);

  return () => {
    cancelToken.cancel();
  }
}, []);

const logout = () => {
  signout(() => {
    history.push('/signin');
  });
};

return (
  <div>
    <button onClick={() => logout()}>Sign out </button>
  </div>
);

Upvotes: 2

Related Questions