Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/github/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 间隔不会导致在react组件中重新渲染_Reactjs_Setinterval_React Hooks - Fatal编程技术网

Reactjs 间隔不会导致在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() {

我正在使用useffect react钩子设置倒计时变量的间隔。我注意到,当我的浏览器中的选项卡处于非活动状态时,内部选项卡将停止工作。如果该选项卡处于活动状态,代码将完全按照预期工作

有更好的方法吗?下面是一个代码示例

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并“不做任何事情”因为用户没有查看您的页面。当页面恢复焦点时,请重新安排设置间隔,并立即触发检查功能。很可能已通过阈值,这将得到正确处理。