间隔不导致React组件重新渲染

时间:2019-08-13 10:59:02

标签: reactjs setinterval react-hooks

我正在使用useEffect 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>
  );
}

我已经在Dan Abramov的帖子here中实现了有关此问题的解决方案。但是,当选项卡处于非活动状态时,Dan的解决方案也不会呈现。

2 个答案:

答案 0 :(得分:0)

请注意,这就是浏览器的工作方式:不活动的选项卡被取消优先级,计时器受到严重限制。请记住,php_sqlsrv_7_nts_x86setTimeout最明显地是不是“在X毫秒过去之后运行代码”,它们是“至少在之后 X运行代码。 ms过去了”,但不能保证事情不会真正发生,因为调度(例如,选项卡是否处于活动状态,甚至在OS可以通知浏览器的范围内是可见的)以后,甚至仅仅是因为一些JS代码需要花费比指定的时间间隔更长的时间才能完成,因此从字面上看,您的超时直到完成后才能触发(因为JS是单线程的)。

对于Firefox,请参见https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API#Policies_in_place_to_aid_background_page_performance,了解如何在计时器上执行节流;对于Chrome,请参见https://developers.google.com/web/updates/2017/03/background_tabs

(对于任何其他浏览器,网络搜索都应该为您找到类似的文档。)

但是,请考虑一下使选项卡成为后台进程的含义:如果您的用户看不到您的选项卡,为什么您根本需要更新任何内容?您的用户将无法看到这些更新。相反,可以考虑在选项卡变得不可见时挂起纯视觉任务,然后在选项卡再次变得可见时恢复它们,并使用时钟检查来确定“是否需要发生”。

实际上,如果您使用setIntervalsetInterval,即使在前台选项卡上也很重要:10个连续的setTimeout不会 暗示它“一旦完成,将精确到1秒,这意味着我们完成后至少要 1秒钟,但是我们可以很容易地在7号或7号之前达到“一秒钟后”的标记。因为JS是单线程的,所以会触发第8个超时,并且如果某些任务花费了一段时间,则直到该任务完成后才会激发您的超时。因此,您至少要为此更新代码。

答案 1 :(得分:-1)

可能是因为useEffect调用在第一个渲染之后使用clearInterval函数。这是useEffect的清理与返回的函数Example Using Hooks一起工作的方式。