Reactjs “反应”;间隔;一直都是一样的状态
我将react 16.10与typescript一起使用。 我有以下代码:Reactjs “反应”;间隔;一直都是一样的状态,reactjs,typescript,Reactjs,Typescript,我将react 16.10与typescript一起使用。 我有以下代码: const [state, setState] = useState<State>({ test: 1 }); //On component mount we start our interval useEffect(() => { const timerID = setInterval(timer, 5000); //every 5 s
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
</>
);
const[state,setState]=useState({
测试:1
});
//在组件安装上,我们开始我们的间隔
useffect(()=>{
const timerID=setInterval(计时器,5000);//每5秒
返回函数cleanup(){
//当我们离开组件时,我们停止计时器
清除间隔(timerID);
};
}, []);
函数计时器(){
如果(state.test==3){
//他将永远不会进入此代码功能
}
setState({…state,test:3});//下次我们应该有值3,但它从来没有这个值?!?!
}
返回(
输出为{state.test}//首先显示1,5秒后显示3。工作正常
);
我正在将测试值更改为“计时器”间隔中的数字3。这个州运转良好。我可以看到组件中的值,看到数字从1切换到3
但在定时器功能中,该值从未改变。它每次都具有默认值1
我做错了什么?我发现了几个潜在问题,首先您需要调用
this.state
和this.setState
。我猜州是未定义的,但这个州不会。您也不需要在setState函数中扩展状态,this.setState({test:3})
已经足够好了,setState函数可以帮您完成这项工作
其次,您需要为每个更改更新状态,看起来只有当测试值为3时才更新状态,我很惊讶这个实现竟然是3。您需要向
useffect
//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
//在组件装载时,我们开始间隔
useffect(()=>{
const timerID=setInterval(计时器,5000);//每5秒
返回函数cleanup(){
//当我们离开组件时,我们停止计时器
清除间隔(timerID);
};
},[state.test]);// 您没有做错任何事情,您的useffect()
在内存中有一个完全不同的值,并且在不知道有关useffect()
的这种行为的情况下,内存中没有任何内容告诉useffect()
停止查看旧值并开始查看新值。正如Hardik所写的,您的useffect()
只被调用一次,因此您仍然拥有最初在其中调用的旧值,并且useffect
不知道您的计时器从此发生了更改。它将永远引用该原始值
您可以做的是完全删除空数组作为第二个参数,您将注意到行为上的差异
按照Hardik的建议,直接引用您在状态中使用的变量似乎是一种可行的方法
同样地,useffect()
不会被再次调用,因此,它内部的任何内容都不会再次运行,因此它都处于陈旧引用中
facebook团队给出的缓解此漏洞的提示之一:
- 如果有引用状态、道具或上下文值的useEffect函数,请将它们添加到依赖项列表中。换句话说,如果您有一个名为trackId的道具,您可能希望执行以下操作:
useEffect(() => {
trackId
}, [trackId]);
它的功能组件,因此不会有这一点。谢谢,它正在工作,但这是最好的解决方案吗?感觉很不对劲。让我解释一下:每次值测试更改时,它都会运行清理函数,销毁间隔并创建一个新的间隔,每次值更改时。单凭这一点感觉并不好。这是一个缩小的例子,在现实中,我有许多集合状态,不仅改变一个值,而且改变许多。这意味着我必须在useEffect方法[…]中设置我更改的每个状态。是的,这是正确的方法。但如果它不适合你的情况。最好的情况是使用类组件
。当功能组件变大时会变得复杂。或者,您可以使用多个useffect
,以确保在REACT还声明它们不会马上弃用类组件时需要更改哪些内容。因此,如果您填写的内容不正确,请使用它们:)您正在编写“…只是一个带有useffect()的讨厌的bug”。这真的是一个bug还是按设计工作?react团队是否会在下一个版本中更改此行为?你有这方面的问题吗?@Paul,说得好,我想它是按设计工作的,顺便问一下,你会有一些文件说明这一点吗?这对我们许多人都有帮助。