setInterval 运行机制 clearInterval 失效场景

通过一个变量来控制页面逻辑轮询,可以开启轮询,满足特定条件结束轮询,一般大家第一个想到的就是 setInterval
setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数

第一种方案

定时器正常启动,但是 clearInterval() 之后轮询依然没有停止

原因: 直接定义变量的话,改变这个变量,组件不会重新渲染,定时器清除了,但是页面上的轮询还在继续,看起来像是清除失败

  let foo = null;
  useEffect(() => {
    if (view) {
      foo = setInterval(() => {
        // do someting
      }, 2000);
    } else {
      clearInterval(foo);
      foo = null
    }
  }, [view]);

最终解决方案

将变量保存在 state 中,使用一个变量来控制轮询的启动暂停

state跟上边的直接定义变量的区别:
setState 是异步执行的,当 setState 方法被调用后,方法会将状态传递给组件更新器,让组件更新器将状态临时存储起来,状态临时保存完成后判断当前是否为批量更新模式,如果是,将组件更新器添加到更新队列中;如果不是,直接更新组件

  const [foo, setFoo] = useState(null);
  useEffect(() => {
    if (view) {
      setFoo(setInterval(() => {
        // do someting
      }, 2000));
    } else if (foo) {
      clearInterval(foo);
      setFoo(null);
    }
  }, [view]);

补充 useEffect 的执行周期

useEffect 没有第二个参数的时候,组件初始化及更新都会执行

useEffect(() => {
    // do someting
 });

useEffect 第二个参数为空数组时,仅在组件初始化时调用一次

useEffect(() => {
    // do someting
 }, []);

useEffect 第二个参数有一个或多个值时,其中值有变化就执行,多个值经过比较只要有一个变化就执行

useEffect(() => {
    // do someting
 }, [params1, params2]);

你可能感兴趣的:(setInterval 运行机制 clearInterval 失效场景)