Ad

React "interval" Has Always The Same State

- 1 answer

I am using react 16.10 with typescript. I have this code:

  const [state, setState] = useState<State>({
        test: 1
    });  

    //On component mount we start our interval
    useEffect(() => {
        const timerID = setInterval(timer, 5000); //every 5 seconds

        return function cleanup() {
            //When we leave component we stop the timer
            clearInterval(timerID);
        };
    }, []); 

   function timer() {
        if(state.test === 3){
            //HE WILL NEVER ENTER THIS CODE FUNCTION
        }

        setState({...state, test: 3}); // Next time we should have the value 3, BUT IT HAS NEVER THIS VALUE?!?!
    }

   return (
        <>
     <span>The output is {state.test}</span> //First it is showing 1, after 5 seconds 3. Working great
        </>
    );

I am changing the value of test to the number 3 in the interval "timer". setState is working fine. I can see the value in my component, seeing the number switching from 1 to 3.

But in the timer function the value is never changed. It has every time the default value of 1.

What I am doing wrong?

Ad

Answer

You need to add dependency to useEffect

 //On component mount we start our interval
  useEffect(() => {
      const timerID = setInterval(timer, 5000); //every 5 seconds

      return function cleanup() {
          //When we leave component we stop the timer
          clearInterval(timerID);
      };
  }, [state.test]); // <- here add dependency

Reason

Your effect function is called only once when component is mounted and it stored timer functions reference. now when you state changes your timer function is also updated outside but not inside of useEffect.

useEffect still uses old reference when state was 1 so inside it State always going to be 1 for that referred timer function

Now when you pass state.test as dependency. when state get changed your effect will updated and it now start using new timer function which has new state.

So now, you can have updated state in your timer function. and your condition can evaluate correctly.

if any doubts please comment.

Ad
source: stackoverflow.com
Ad