Javascript 反应';s状态更新与ref异步更新
React的状态更新是异步的,这就是为什么您不应该在设置后立即尝试使用状态(如日志记录或任何其他读取操作)。但是,只有async关键字似乎无法提供React如何更新状态的总体情况 此状态更新与异步执行的ref更新有何不同 考虑以下代码段,其中我们模拟了Javascript 反应';s状态更新与ref异步更新,javascript,reactjs,Javascript,Reactjs,React的状态更新是异步的,这就是为什么您不应该在设置后立即尝试使用状态(如日志记录或任何其他读取操作)。但是,只有async关键字似乎无法提供React如何更新状态的总体情况 此状态更新与异步执行的ref更新有何不同 考虑以下代码段,其中我们模拟了statefulRef的async更新。即使在异步更新statefulRef之后,如果在更新之后访问它,我们也会得到最新的值。但状态情况并非如此。我知道render和closure都参与了对状态更新的解释,但我想得到一个详细的答案,解释异步行为的差
statefulRef
的async更新。即使在异步更新statefulRef
之后,如果在更新之后访问它,我们也会得到最新的值。但状态
情况并非如此。我知道render和closure都参与了对状态更新的解释,但我想得到一个详细的答案,解释异步行为的差异,我们在下面看到:-
const{
useState,
useRef
}=反应
函数App(){
const[state,setState]=useState({current:0});
const statefulRef=useRef(0);
函数updateState(){
//下面是异步操作
setState({current:state.current+1});
//下面是异步日志记录
setTimeout(()=>console.log(“反应状态:”,state.current),500);
}
函数updateRef(){
//下面是异步操作
setTimeout(()=>statefulRef.current+=1200);
//下面是异步日志记录
setTimeout(()=>console.log(“React ref:”,statefulRef.current),500);
}
报税表(
更新状态
更新参考
)
}
ReactDOM.render( ,document.getElementById(“根”)代码>
状态
在程序执行进入updateState
函数时被捕获。因此,console.log
将显示一个过时的值,无论是否带有setTimeout
对于statefulRef
也是如此,它是在执行updateRef
开始时捕获的。但是statefulRef
是一个对象,在JavaScript中,对象是引用。捕获的是引用,而不是值(属性的值)。因此,即使statefulRef
不会改变,statefulRef.current
可能会改变。而对于状态
来说,事情或多或少是这样的:
函数updateRef(){
常数电流=状态参考电流;
//下面是异步操作
setTimeout(()=>(statefulRef.current+=1),200;
//下面是异步日志记录
setTimeout(()=>console.log(“React ref:,current”),500;
}
更新:事实上,状态
本身是一个对象(如更新的问题中所述),变化不大<代码>设置状态
将旧值替换为新值,在不更改状态
本身的情况下,它不会分配给状态
的属性。您可以通过执行state.current=1
来实现类似的效果,但您不应该这样做,因为这会打破React关于状态管理的假设。长话短说,状态关闭是这种行为的原因。控制台显示过期的state
值的原因是传递给setTimeout
的回调引用了闭包捕获的过期的state
。@codemonkey所以我们可以说react的状态更新不是有时间限制的,而是有渲染限制的,也就是说,只有在新的渲染中才会更新能够访问新状态。无论您在计时器中提到的等待时间有多长,它都将始终保持来自上一次渲染的过时关闭状态。setTimeout
可以等待一周,它仍然会引用旧值。另一方面,statefulRef
变量不受闭包机制的约束。将state
作为对象更新帖子。它不会更改任何内容<代码>设置状态
更改整个状态,而不是其内容。我会更新答案。