我已经在顶层组件(App)中创建了一些状态,但是当更新此状态时,useEffect()
中定义的异步函数似乎没有读取更新的状态(它仍然使用以前的值),详细信息如下:
我试图检索在useEffect()
中定义的异步函数toggleProcessing
中的const processing
的状态,以便当processing
变为false时,异步函数退出while循环,但是,似乎当processing
更新为false时,while循环仍然继续执行。
行为应如下所示:按下"开始处理"按钮应每两秒控制台记录一次"处理...",当再次按下同一按钮(现在标记为"停止处理")时,控制台应记录"停止处理"。但是,实际上,控制台从不记录"停止处理",而是永远连续记录"处理"。
下面是代码:
import React, { useState, useEffect} from 'react'
const App = () => {
const [processing, setProcessing] = useState(false)
const sleep = (ms) => {
return new Promise(resolve => setTimeout(resolve, ms))
}
useEffect(() => {
const toggleProcessing = async () => {
while (processing) {
console.log('Processing...')
await sleep(2000);
}
console.log('Stopping Processing')
}
if (processing) {
toggleProcessing() // async function
}
}, [processing])
return (
<>
<button onClick={() => setProcessing(current => !current)}>{processing ? 'Stop Processing' : 'Begin Processing'}</button>
</>
)
}
export default App;
它实际上只是能够在异步函数中读取processing
的更新状态,但我还没有找到这样做的方法,尽管阅读了类似的帖子。
先谢谢你!
3条答案
按热度按时间pqwbnv8z1#
如果你想在使用超时时访问一个状态,最好保留一个对该变量的引用,你可以使用
useRef
钩子来实现这一点,只需添加一个带有处理值的ref,并记得更新它。icomxhvb2#
我很感兴趣这个是如何工作的,以及基于公认答案的最终解决方案是什么。我根据Dan Abramov的
useInterval
钩子提出了一个解决方案,并认为这个解决方案以及一些相关资源的链接可能对其他人有用。我很好奇,你决定使用
setTimeout
并引入async/await
和while
循环,而不是使用setInterval
,有什么特别的原因吗?我想知道其中的含义。你会在卸载所有正在运行的计时器时处理clearTimeout
吗?你的最终解决方案是什么样子的?带useInterval的演示/解决方案
https://codesandbox.io/s/useinterval-example-processing-ik61ho
相关链接
Dan Abramov - Making setInterval Declarative with React Hooks
SO Question: React hooks - right way to clear timeouts and intervals
q3qa4bjr3#
下面是工作代码: