状态更新如何与异步函数一起工作?



我刚开始学习React,在" Series of state update "一节中我对异步延迟在状态更新期间的工作方式感到困惑,例如:

export default function RequestTracker() {
const [pending, setPending] = useState(0);
const [completed, setCompleted] = useState(0);
async function handleClick() {
setPending(p=>p + 1);
await delay(pending*3000);

setPending(p=>p - 1);
setCompleted(c=>c + 1);
}

我认为这段代码将设置挂起为(pending+1),并在3秒后减少1。然而,当我点击按钮时,"pending"没有增加,"complete"值立即增加,这意味着没有延迟,"pending"值始终为0。

然后我将延迟函数改为**pending*3000+3000**代码按照我的预期工作(将挂起设置为(pending+1)并在3秒后减少1)

这意味着'pending'值没有保持在0。你能解释在两种情况下挂起的值是如何不同的吗?

setPending的调用不会改变pending的值:它不能,因为它没有办法关闭变量。pending值与调用RequestTracker函数时返回的值相同。

因为每次你的组件被渲染时,RequestTracker都会被再次调用,你会得到pending改变的错觉,因为下一次你的组件被渲染时,useState会被再次调用,而这次它会返回之前你调用setPending时传递的值。

但是当你在调用setPending之后立即检查pending的值时,你仍然会看到它在调用之前的值。有几种方法可以解决这个问题。这里有一个:

async function handleClick() {
const newPendingValue = pending + 1;
setPending(newPendingValue);
await delay(newPendingValue*3000);

setPending(p=>p - 1);
setCompleted(c=>c + 1);
}

请注意,由于异步延迟,以后调用setPendingsetCompleted使用函数仍然是一个好主意:它们需要知道pendingcompleted在调用时的值,而不是调用处理程序的时间。

另外:您可能会尝试在提供给setPending的函数中捕获p的值,并在稍后使用该值,但是您传递给setPending的函数不一定会被同步调用,因此这不是一种可靠的方法。

相关内容

  • 没有找到相关文章

最新更新