看似清理了定时器,实际定时器仍然存在,并定时触发方法

38 阅读1分钟

错误代码示范:

let timer;

useEffect(() => {
    getModelAlertInfoListTimely(filterRef.current);
    timer = setInterval(() => {
      getModelAlertInfoListTimely(filterRef.current);
    }, 60 * 1000);
    return () => {
      clearInterval(timer);
    };
  }, [filterRef.current]);
  
//切换状态  
const onRtSwitchChange = value => {
    setRtSwitch(value);
    if (value) {
      timer = setInterval(() => {
        getModelAlertInfoListTimely(filterRef.current);
      }, 60 * 1000);
    } else {
      clearInterval(timer);
    }
  };
  
  
  
  return(
   <div className={css.operationSwitch}>
      <Switch checked={rtSwitch} onChange={onRtSwitchChange} />
      <span>实时刷新</span>
    </div>
    )

实际运行效果: 当value为false时,仍然会调用getModelAlertInfoListTimely()

从代码逻辑来看,getModelAlertInfoListTimely() 只会在 value 为 true 时被 setInterval 定时调用。当 value 为 false 时,clearInterval(timer) 会清除定时器,理论上不会继续调用 getModelAlertInfoListTimely()。
实际观察到 value 为 false 时仍然调用了 getModelAlertInfoListTimely(),可能的原因包括:
  • timer 变量未正确清除:

    检查 timer 是否为全局变量或未正确重置。建议将 timer 声明为组件内的 useRef 或 useState 持久化变量,避免因重新渲染丢失引用。

  • clearInterval 未生效:

    可能 timer 的值在 clearInterval 调用时已无效(例如被覆盖或未正确传递)。

  • 异步延迟问题:

    如果 value 快速切换(如短时间内从 true 变 false),可能存在尚未执行的定时任务。

修复建议:

// 使用 useRef 持久化 timer
const timerRef = useRef<NodeJS.Timeout | null>(null);

 useEffect(() => {
    getModelAlertInfoListTimely(filterRef.current);
    timerRef.current = setInterval(() => {
      getModelAlertInfoListTimely(filterRef.current);
    }, 60 * 1000);
    return () => {
      clearInterval(timerRef.current);
    };
  }, [filterRef.current]);

const onRtSwitchChange = value => {
  setRtSwitch(value);
  if (value) {
    // 先清除已有定时器
    if (timerRef.current) clearInterval(timerRef.current);
    timerRef.current = setInterval(() => {
      getModelAlertInfoListTimely(filterRef.current);
    }, 60 * 1000);
  } else {
    if (timerRef.current) {
      clearInterval(timerRef.current);
      timerRef.current = null; // 重置引用
    }
  }
};

return(
   <div className={css.operationSwitch}>
      <Switch checked={rtSwitch} onChange={onRtSwitchChange} />
      <span>实时刷新</span>
    </div>
    )
这样修改后,可以确保定时器被正确管理,避免残留调用。