Javascript useEffect中的状态未更新

Javascript useEffect中的状态未更新,javascript,reactjs,setinterval,Javascript,Reactjs,Setinterval,我目前正在ReactJS中构建一个计时器以供练习。目前我有两个组件,一个定时器组件,它显示时间,并在安装时设置间隔。我还有一个应用程序组件,它可以跟踪主状态,例如计时器是否暂停的状态以及计时器的当前值 我的目标是,当我点击暂停按钮时,计时器停止递增。目前,我已尝试通过以下方式实现这一目标: if(!paused) tick(time => time+1); 在我看来,当暂停为false时,应该只增加时间状态。但是,当我通过单击我的按钮更新暂停状态时,setTimeout中的暂停状态

我目前正在ReactJS中构建一个计时器以供练习。目前我有两个组件,一个定时器组件,它显示时间,并在安装时设置间隔。我还有一个应用程序组件,它可以跟踪主状态,例如计时器是否暂停的状态以及计时器的当前值

我的目标是,当我点击暂停按钮时,计时器停止递增。目前,我已尝试通过以下方式实现这一目标:

if(!paused) 
  tick(time => time+1);
在我看来,当暂停为false时,应该只增加时间状态。但是,当我通过单击我的按钮更新暂停状态时,setTimeout中的暂停状态不会改变。我猜setTimeout正在暂停状态上形成一个闭包,因此当状态改变时它不会更新。我尝试将paused作为依赖项添加到useEffect,但这导致每当paused发生更改时,都会出现多个超时

const{useState,useffect}=React; 常量计时器={时间,暂停,勾选}=>{ useEffect=>{ 常量计时器=设置间隔=>{ 如果!paused/`paused`不变? 滴答声时间=>time+1; }, 1000; }, []; 返回{time}s

} 常量应用==>{ const[time,setTime]=useState0; const[paused,setPaused]=useStatefalse; 常量切换暂停==>setPausedpaused=>!暂停; 回来 {暂停?'Play':'Pause'} ; } ReactDOM.render,document.body;
要停止计时器,请返回清除useEffect间隔的功能

React在组件卸载时执行清理。但是,正如我们前面所了解的,效果会在每次渲染时运行,而不仅仅是一次。这就是为什么React还会在下次运行效果之前清除上一次渲染中的效果

资料来源:

您还应该传递暂停的依赖项数组,以停止useEffect在每次重新渲染时创建新的间隔。如果添加[paused],则仅在暂停更改时创建新的间隔

const{useState,useffect}=React; 常量计时器={时间,暂停,勾选}=>{ useEffect=>{ 常量计时器=设置间隔=>{ 如果!paused/`paused`不变? 滴答声时间=>time+1; }, 1000; return=>clearIntervaltimer; },[暂停]; 返回{time}s

} 常量应用==>{ const[time,setTime]=useState0; const[paused,setPaused]=useStatefalse; 常量切换暂停==>setPausedpaused=>!暂停; 回来 {暂停?'Play':'Pause'} ; } ReactDOM.render、document.getElementByIdroot;
要停止计时器,请返回清除useEffect间隔的功能

React在组件卸载时执行清理。但是,正如我们前面所了解的,效果会在每次渲染时运行,而不仅仅是一次。这就是为什么React还会在下次运行效果之前清除上一次渲染中的效果

资料来源:

您还应该传递暂停的依赖项数组,以停止useEffect在每次重新渲染时创建新的间隔。如果添加[paused],则仅在暂停更改时创建新的间隔

const{useState,useffect}=React; 常量计时器={时间,暂停,勾选}=>{ useEffect=>{ 常量计时器=设置间隔=>{ 如果!paused/`paused`不变? 滴答声时间=>time+1; }, 1000; return=>clearIntervaltimer; },[暂停]; 返回{time}s

} 常量应用==>{ const[time,setTime]=useState0; const[paused,setPaused]=useStatefalse; 常量切换暂停==>setPausedpaused=>!暂停; 回来 {暂停?'Play':'Pause'} ; } ReactDOM.render、document.getElementByIdroot;
setInterval第一次捕获暂停值时,您需要删除该间隔,每次更改暂停时间时重新创建该间隔


您可以查看本文了解更多信息:

setInterval第一次捕获暂停值时,您需要删除该间隔,每次更改暂停时间时重新创建它

您可以查看本文了解更多信息:

您可以使用Dan的useInterval钩子。我不能比他解释得更好,你应该用这个

钩子看起来像这样

函数useIntervalcallback,延迟{ const savedCallback=React.useRef; //记住最近的回拨。 React.useffect=>{ savedCallback.current=回调; },[回调]; //设置间歇时间。 React.useffect=>{ 功能记号{ savedCallback.current; } 如果延迟!==null{ let id=setIntervaltick,延迟; return=>clearIntervalid; } },[延迟]; } 然后像这样在计时器组件中使用它

常量计时器={时间,暂停,勾选}=>{ useInterval=>{ 如果!暂停时间=>time+1; }, 1000; 返回{time}s

; }; 我相信区别在于useInterval钩子知道它的依赖项已暂停,而setInterval则没有。你可以使用Dan的useInterval钩子。我再也解释不清楚了 告诉他你应该用这个

钩子看起来像这样

函数useIntervalcallback,延迟{ const savedCallback=React.useRef; //记住最近的回拨。 React.useffect=>{ savedCallback.current=回调; },[回调]; //设置间歇时间。 React.useffect=>{ 功能记号{ savedCallback.current; } 如果延迟!==null{ let id=setIntervaltick,延迟; return=>clearIntervalid; } },[延迟]; } 然后像这样在计时器组件中使用它

常量计时器={时间,暂停,勾选}=>{ useInterval=>{ 如果!暂停时间=>time+1; }, 1000; 返回{time}s

; };
我相信区别在于useInterval钩子知道它的依赖项已暂停,而setInterval则没有。

Ah!我喜欢这个!这不会在每次设置时间间隔时重新运行useEffect吗?啊!我喜欢这个!这不是每次setInterval设置的时候都会重新运行useEffect吗?