Reactjs “反应”;间隔;一直都是一样的状态

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

我将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 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,说得好,我想它是按设计工作的,顺便问一下,你会有一些文件说明这一点吗?这对我们许多人都有帮助。