2

I've read some good practices in reactjs using useEffect. I have a situation which I separated my function to fetch the data and call it on the useEffect hook. How could I make some cleanup functions in this situation. ?

I've seen some useEffect cleanup like these:

useEffect(() => {
  let isActive = true;

  fetch('https://jsonplaceholder.typicode.com/todos/1')
    .then((response) => response.json())
    .then((data) => {
      if (isActive) {
        setTodo(data);
      }
    })
    .catch((error) => console.log(error.message));

  return () => {
    isActive = false;
  };
}, []);

From the example above, the fetch function is inside with useEffect, now how can I perform some cleanup if something like this situation:

const getTodos = async () => {        
        try {
            const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
            const todos = await response.json();
            if(todos) {
                setTodos(todos);
            }
        }catch(e) {
            console.log(e);
        }
    }    

useEffect(() => {
        let mountedTodos = true;
        getTodos();

        return () => {
            mountedTodos = false;
        }
    },[])
1
  • You can keep the isActive in global scope or define the getTodos inside the useEffect. Commented Jun 30, 2022 at 6:53

2 Answers 2

1

This could be handled in multiple ways.

  • You could have mountedTodos as a global variable outside the component.

  • You could defined mountedTodos as an object and pass it to getTodos function.

However, I suggest you to use an AbortController

const getTodos = async (signal) => {        
    try {
        const response = await fetch(/*url*/, { signal });
            const todos = await response.json();
            if(!signal.aborted) {
                setTodos(todos);
            }
        }catch(e) {
            console.log(e);
        }
    }    

useEffect(() => {
   const abortController = new AbortController();
   getTodos(abortController.signal);

   return () => abortController.abort();
},[])

Note: You should add getTodos in the dependency array of the useEffect hook and to avoid infinite loop of state update and re-render, wrap getTodos in useCallback hook.

Sign up to request clarification or add additional context in comments.

1 Comment

Btw, the first option that you have suggested, I don't want to apply it because when dealing with alot of cleanup functions, I may also declared some global variables.
1

Create a flushTodos function and call it in return statement of useEffect and in that function just update your state of todos to blank array.

return () => {
  flushTodos();
}

And other option is: I hope you are using todos as a state so you can directly update the state in return statement of useEffect like this:

return () => {
  setTodos([]);
}

1 Comment

What happens when the response is received after flushTodos function has been called and component has unmounted? getTodos function will update the state of an unmounted component.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.