Reactjs 间隔不会导致在react组件中重新渲染
我正在使用useffect react钩子设置倒计时变量的间隔。我注意到,当我的浏览器中的选项卡处于非活动状态时,内部选项卡将停止工作。如果该选项卡处于活动状态,代码将完全按照预期工作 有更好的方法吗?下面是一个代码示例Reactjs 间隔不会导致在react组件中重新渲染,reactjs,setinterval,react-hooks,Reactjs,Setinterval,React Hooks,我正在使用useffect react钩子设置倒计时变量的间隔。我注意到,当我的浏览器中的选项卡处于非活动状态时,内部选项卡将停止工作。如果该选项卡处于活动状态,代码将完全按照预期工作 有更好的方法吗?下面是一个代码示例 export default function CountdownTimer({ minutes_left, action }) { const [timeLeft, setTimeLeft] = useState(); function updateTimer() {
export default function CountdownTimer({ minutes_left, action }) {
const [timeLeft, setTimeLeft] = useState();
function updateTimer() {
const remaining = ...work out time left
setTimeLeft(remaining);
}
useEffect(() => {
const interval = setInterval(() => {
updateTimer();
if (timeLeft.asMilliseconds() <= 0) {
action();
clearInterval(interval);
}
}, 1000);
return () => clearInterval(interval);
}, []);
return (
<p>{timeLeft}</p>
);
}
导出默认函数倒计时({minutes\u left,action}){
const[timeLeft,setTimeLeft]=useState();
函数updateTimer(){
剩余常量=…计算剩余时间
setTimeLeft(剩余);
}
useffect(()=>{
常量间隔=设置间隔(()=>{
updateTimer();
if(timeLeft.asmillseconds()清除间隔(interval);
}, []);
返回(
{timeLeft}
);
}
我已经在Dan Abramov的帖子中实现了关于这个问题的解决方案。但是,Dan的解决方案在选项卡处于非活动状态时也不会呈现。可能是因为useEffect调用在第一次呈现后使用clearInterval函数。下面是清理
useEffect
如何与返回的函数一起工作-。请注意,这就是为什么浏览器工作:非活动选项卡被取消优先级,计时器被严重限制。请记住,setTimeout
和setInterval
最明显地不是“在X ms通过后运行代码”,它们是“在至少X ms通过后运行代码”,但不能保证事情不会因为调度而在很长时间后发生(例如,该选项卡是否处于活动状态,或者在操作系统通知浏览器的范围内是否可见)或者甚至仅仅是因为一点JS代码的完成时间比指定的时间间隔长,因此在完成之前无法触发超时(因为JS是单线程的)
对于Firefox,请参阅在计时器上执行何种节流,对于Chrome,请参阅
(对于任何其他浏览器,web搜索都会找到类似的文档。)
但是,考虑一下标签成为后台进程意味着什么:如果你的用户看不到你的标签,为什么你需要更新任何东西?你的用户将无法看到这些更新。相反,当标签变得不可见时,考虑暂停纯视觉任务,然后在标签再次可见时恢复它们。使用时钟时间检查来确定是否“事情需要发生”
事实上,如果使用
setInterval
或setTimeout
,即使在前台选项卡上也必须这样做:连续10次setTimeout(…,100)
并不意味着它们完成后正好是1秒,这意味着我们完成时至少要晚1秒,但我们可以很容易地达到“1秒后”在第7次或第8次超时触发时进行标记,因为JS是单线程的,如果某个任务需要一段时间,那么在该任务完成之前,您的超时不会触发。因此,无论如何,您至少需要为此更新您的代码。Mm实际上……我发现这有帮助,但是它仍然变得不同步,现在通常只有few秒。我更新了描述,添加了一条关于尝试该博客文章中的解决方案的注释。他们也遇到了这个问题。我正在考虑可能每30秒左右做一次请求,以重新同步计时器。如果你需要精确到秒,间隔通常是处理倒计时的一个相当糟糕的工具。你会怎么做d您建议使用setInterval和setTimeout代替“不更新”。标记“开始时间”在一些可访问的变量/const中,然后捕获您的setInterval
,以调用将当前时间与该开始时间进行比较的函数。如果差值超过阈值,则触发需要发生的情况并清除间隔。但如果用户使页面模糊,请清除setInterval并“不做任何事情”因为用户没有查看您的页面。当页面恢复焦点时,请重新安排设置间隔,并立即触发检查功能。很可能已通过阈值,这将得到正确处理。