0

With React's class-based components, the component's state values can be read from within a setInterval within a class method, as logic elsewhere in the component changes the state:

...
constructor(props) {
  super(props);
  this.state = {
    someChangingStateValue: 'initial value'
  }
}
...
// Elsewhere, at random:
this.setState({someChangingStateValue: 'suddenly changed'})
...
_handleLoop() {
  setInterval(() => {
    console.log(this.state.someChangingStateValue)
    console.log("The above line prints the current state value correctly.")
  }, 500)
}
...

However, this pattern can't be used with hooks-based functional React components:

...
[someChangingStateValue, setSomeChangingStateValue] = useState('initial value')
...
// Elsewhere, at random:
setSomeChangingStateValue('suddenly changed')
...
const _handleLoop () => {
  setInterval(() => {
    console.log(someChangingStateValue)
    console.log("The above line would always print 'initial value'.")
  }, 500)
}
...

What is the best way to accomplish this with these functional components?

sunw
  • 535
  • 5
  • 29
  • can you add please the reason why you are trying to do this. It seems like XY problem – nikoss May 16 '20 at 22:30
  • The state setter can receive a callback function that gets the current state value: `setSomeChangingStateValue(currentValue=>)` if you want to change it then return the changed value but if you don't then return the value you receive: `setSomeChangingStateValue(currentValue=>{do something with current value; return currentValue;})` – HMR May 16 '20 at 22:32
  • 1
    Does this answer your question? [React Hooks useState+useEffect+event gives stale state](https://stackoverflow.com/questions/55154186/react-hooks-usestateuseeffectevent-gives-stale-state) – Henry Woody May 16 '20 at 22:47

1 Answers1

1

The cleanest solution for the moment seems to be to create a reference using useRef():

import React, { useState, useRef } from "react";
...
[someChangingStateValue, setSomeChangingStateValue] = useState('initial value')
const someChangingStateValueRef = useRef();
someChangingStateValueRef.current = someChangingStateValue;
...
// Elsewhere, at random:
setSomeChangingStateValue('suddenly changed')
...
const _handleLoop () => {
  setInterval(() => {
    console.log(someChangingStateValueRef.current)
    console.log("The above line prints the current state value correctly.")
  }, 500)
}
...
sunw
  • 535
  • 5
  • 29