Reputation: 3783
How can I adjust the below code so that after "loop" button is pressed, and then "change data" button is pressed, I can see the loop print changed data - that is, "bar" not "foo"?
https://codesandbox.io/s/react-hooks-playground-forked-gn5yw
const sleep = async(ms: number) => new Promise(r => setTimeout(r, ms))
const Looper = () => {
const [data, setData] = React.useState<string>('foo')
const runOnce = () => {
console.log(data)
}
const loop = async() => {
while (true) {
runOnce()
await sleep(1000)
}
}
return (
<div>
<button onClick={loop}>Loop</button>
<button onClick={runOnce}>Run once</button>
<button onClick={() => setData('bar')}>Change data in state</button>
</div>
)
}
Upvotes: 0
Views: 34
Reputation: 370759
Since the data
change doesn't result in any visual changes in the component, it doesn't need to be state. The runOnce
function containing the data from the old closure is the problem (data
is declared with const
, after all - it can't change for a given invocation of loop
)
Use a ref instead:
const dataRef = useRef('foo');
const runOnce = () => {
console.log(dataRef.current)
}
<button onClick={() => { dataRef.current = 'bar'; }}>Change data in state</button>
Upvotes: 1