Search code examples
reactjsuse-effect

Problem with asynchronous tasks in useEffect hook


I have an error like this:

index.js:1 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. at ToDoAdder (http://localhost:3000/static/js/main.chunk.js:193:3)

here's my code:

import React, { useState } from 'react';
import { useEffect } from 'react';
import { Trash, Pen, CheckLg, XCircleFill } from 'react-bootstrap-icons';
import { Button } from 'react-bootstrap';
import store from '../../store';

function ToDoAdder({ data }) {
  const [user, setUser] = useState({});

  const { id, title, completed, userId } = data;

  useEffect(() => {
   fetchUsers();
  }, [user]);

  const fetchUsers = async () => {
    const data = await fetch(
      `https://jsonplaceholder.typicode.com/users/${userId}`
    );
    const users = await data.json();
    setUser(users);
    return user;
  };

  const handleTodoRemove = () => {
    console.log(id);
    store.dispatch({ type: 'remove/todo', payload: { id } });
  };

  return (
     // here goes some code
  )
}

export default ToDoAdder;

Please help me to fix this problem


Solution

  • That's not an error, that's a warning.

    As it says, your component unmounted (why, we can't tell, since we don't see how it's used) before the async call finished.

    In your case, it doesn't even indicate a memory leak unlike the message insinuates.

    If you want to get rid of the warning, you can guard the setUser call using a hook that checks whether the component is actually still mounted at that point. One such reusable hook is react-use's useMountedState.