我正在将React 16.10与打字稿一起使用。 我有以下代码:
const [state, setState] = useState<State>({
test: 1
});
//On component mount we start our interval
useEffect(() => {
const timerID = setInterval(timer, 5000); //every 5 seconds
return function cleanup() {
//When we leave component we stop the timer
clearInterval(timerID);
};
}, []);
function timer() {
if(state.test === 3){
//HE WILL NEVER ENTER THIS CODE FUNCTION
}
setState({...state, test: 3}); // Next time we should have the value 3, BUT IT HAS NEVER THIS VALUE?!?!
}
return (
<>
<span>The output is {state.test}</span> //First it is showing 1, after 5 seconds 3. Working great
</>
);
我将test的值更改为间隔“ timer”中的数字3。 setState工作正常。我可以在组件中看到该值,看到数字从1切换到3。
但是在计时器功能中,该值从未更改。每次默认值为1。
我做错了什么?
答案 0 :(得分:1)
您需要向useEffect
添加依赖项
//On component mount we start our interval
useEffect(() => {
const timerID = setInterval(timer, 5000); //every 5 seconds
return function cleanup() {
//When we leave component we stop the timer
clearInterval(timerID);
};
}, [state.test]); // <- here add dependency
原因
您的效果函数仅在组件安装并存储timer
函数参考时被调用一次。现在,当您更改状态时,您的timer function
也是updated outside
,而不是inside of useEffect
。
useEffect
仍在state was 1
时使用旧参考,因此inside it State always going to be 1
为此referred timer function
现在,当您通过state.test
作为依赖项时。状态更改后,您的效果将更新,并且现在开始使用具有新状态的新timer function
。
现在,您可以在timer function
中更新状态。并且您的状况可以正确评估。
如有任何疑问,请发表评论。
答案 1 :(得分:0)
您没有做错任何事情,您的useEffect()
在内存中具有完全不同的值,并且不知道有关useEffect()
的这种行为,您什么也没有告诉useEffect()
停止关注旧值并开始查看新值。正如Hardik所写,您的useEffect()
仅被调用一次,因此您仍然具有最初在其中调用的旧值,并且useEffect
不知道您的计时器此后已更改。它将永远引用该原始值。
您可以做的是完全删除空数组作为第二个参数,您会注意到行为上的差异。
按照Hardik的建议,直接引用您在状态中使用的变量是可行的方法。
因此,useEffect()
并没有被再次调用,结果,它里面的任何东西都没有再次运行,因此所有这些都已过时。
facebook团队提供的缓解此错误的提示之一:
当您有一个引用状态,属性或上下文值的useEffect函数时,请将其添加到依赖项列表中。换句话说,如果您有一个名为 trackId 的道具,则需要执行以下操作:
useEffect(() => {
trackId
}, [trackId]);
答案 2 :(得分:-1)
我看到了两个潜在的问题,首先您需要打电话给this.state
和this.setState
。我猜状态是不确定的,但是this.state不会。您也不需要在setState函数中扩展状态,this.setState({ test: 3});
足够好,setState函数可以为您完成此任务。
第二步,您需要为每个更改更新状态,看起来您仅在测试值为3时才更新,对此实现感到惊讶的是3次。