Can't perform a React state update on an unmounted component. This is a no-op

Viewed 827

That's the warning in the console,

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 [index, setIndex] = useState(0);
  const [refreshing, setRefreshing] = useState(false);
  const refContainer: any = useRef();
  const [selectedIndex, setSelectedIndex] = useState(0);
  const navigation = useNavigation();

  useEffect(() => {
    refContainer.current.scrollToIndex({animated: true, index});
  }, [index]);

  const theNext = (index: number) => {
    if (index < departments.length - 1) {
      setIndex(index + 1);
      setSelectedIndex(index + 1);
    }
  };

  setTimeout(() => {
    theNext(index);
    if (index === departments.length - 1) {
      setIndex(0);
      setSelectedIndex(0);
    }
  }, 4000);

  const onRefresh = () => {
    if (refreshing === false) {
      setRefreshing(true);
      setTimeout(() => {
        setRefreshing(false);
      }, 2000);
    }
  };

What should I do to make clean up?

I tried to do many things but the warning doesn't disappear

2 Answers

setTimeout need to use in useEffect instead. And add clear timeout in return

  useEffect(() => {
    const timeOut = setTimeout(() => {
      theNext(index);
      if (index === departments.length - 1) {
        setIndex(0);
        setSelectedIndex(0);
      }
    }, 4000);

    return () => {
      if (timeOut) {
        clearTimeout(timeOut);
      }
    };
  }, []);

Here is a simple solution. first of all, you have to remove all the timers like this.

useEffect(() => {
   return () => remover timers here ;
},[])

and put this

import React, { useEffect,useRef, useState } from 'react'

const Example = () => {
    const isScreenMounted = useRef(true)
    useEffect(() => {
        isScreenMounted.current = true
        return () =>  isScreenMounted.current = false
    },[])
       
    const somefunction = () => {
        // put this statement before every state update and you will never get that earrning
        if(!isScreenMounted.current) return;
        /// put here state update function
    }
    return null
}

export default Example; 
Related