Home > front end >  Can't perform a React state update on an unmounted component. abortCtrl not working
Can't perform a React state update on an unmounted component. abortCtrl not working

Time:10-31

I have a React component that fetches a array of movies and then sets those movies on a state:

// randomBackground.tsx

const [movieData, setMovieData] = useState<IMovie []>([]);

useEffect(() => {
  const abortCtrl = new AbortController();
  const opts = {signal: abortCtrl.signal};
   const fetchData = () => {
    try {
      fetch(baseurl   apikey   rest, opts)
          .then((response) => response.json())
          .then((data) => {
            setMovieData(data.results);
          });
    } catch (e) {
      console.log(e);
    }
  };
 fetchData();
 return () => abortCtrl.abort();
}, []);

I show this component when a user has not logged in:

// app.tsx

return (
  {currentUser.isLoggedIn ? <DashboardComponent /> : <RandomBackground />}
)

When the user logs in the DashboardComponent takes over. But I get the error:

react-dom.development.js?61bb:67 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 RandomBackground

So the randomBackground component tries to set a value on the setMovieData state which doesn't exist anymore.

If I google the error I get a lot post regarding the AbortController or setting an boolean value, but none of them work. Am I implementing the solution incorrectly?

CodePudding user response:

Use a boolean flag to check if the component has been unmounted and update the state only if it has not (been unmounted).

const [movieData, setMovieData] = useState<IMovie[]>([]);

useEffect(() => {
    let isRequestCancelled = false;

    const fetchData = () => {
        try {
            fetch(baseurl   apikey   rest, opts)
                .then((response) => response.json())
                .then((data) => {
                    if (!isRequestCancelled) {
                        setMovieData(data.results);
                    }
                });
        }
        catch (e) {
            console.log(e);
        }
    };

    fetchData();

    return () => {
        isRequestCancelled = true;
    };
}, []);
  • Related