Skip to content Skip to sidebar Skip to footer

Setinterval Is Not Showing Updated State

I have set the state to true before calling the setInterval function. But even though the useEffect hook is being triggered with the new value of the state, it's not being reflecte

Solution 1:

The values inside the function which you pass to useEffect are refreshed on every render, because useEffect uses a new definition of the function you pass to it.

But the function passed to setInterval is defined once and it closes over the old stale value of state. Which has not yet updated.

Closures are tricky with hooks, but the thing to realize is that useEffect creates a new function for each render and hence each time the function closes over a fresh state value.

The trick then is to call your setInterval related code inside a useEffect itself, which itself depends on the changing value of state

React.useEffect(() => {
  if(state) {

    interval = setInterval(() => {
      console.log(state);
    }, 1000);
  } else {
    clearInterval(interval);
  }

}, [state]);

Or, better, use a useInterval hook which takes care of these details for you.

Solution 2:

setInterval always has access to the value of your component's first render because the function passed to setInterval closes around that value and is never redeclared. You can use a custom hook to fix this:

functionuseInterval(callback, delay) {
  const savedCallback = useRef();

  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  useEffect(() => {
    functiontick() {
      savedCallback.current();
    }

    let id = setInterval(tick, delay);
    return() =>clearInterval(id);
  }, [delay]);
}

That implementation and a thorough explanation of the mismatch between React Hooks and setInterval is from Making setInterval Declarative with React Hooks by Dan Abramov, one of the React contributors.

Solution 3:

I'm not a ReactJS expert, but I guess the state you are logging is not refreshed since it is declared once and never refreshed. If React.useState(false) is the method that is giving you your state, you should use it in your interval function.

Here is an example of what I'm trying to explain:

const object = { value: false }


const notRefreshed = object.value// here we are copying the valueconst interval = setInterval(() => {
  const refreshed = object.value// here we are using the reference to copy the latest valueconsole.log("refreshed", refreshed)
  console.log("notRefreshed", notRefreshed)
}, 500)


setTimeout(() => object.value = true, 1600)

setTimeout(() =>clearInterval(interval), 2600)

Solution 4:

If you want to reaload your component whenever your state change you should create your useEffect like this.

React.useEffect(() => {
    console.log('State updated to', state);
}, [state]);

The way you created is the same as componentDidMount() with an array as the second parameter it's like componentDidUpdate() with it's dependencies. So, your component will re-render whenever your state change.

To solve the infinity call of setTimeout you can do this where you create the function

React.useCallback(() => {
    setInterval(() => {
        console.log(state);
    }, 1000);
})

with this React will know that you want to create this function just once.

Post a Comment for "Setinterval Is Not Showing Updated State"