React:ClearInterval 并立即重新开始

React: ClearInterval and Immediately Start Again

我有一个组件可以触发一个计时器,该计时器每 30 秒更新一次并发出一个 axios 请求。它使用 useRef 设置为每 30 秒更新一次函数 handleStart 被触发。


  const countRef = useRef(null);
  const lastUpdatedRef = useRef(null);
  const [lastUpdated, setLastUpdated] = useState(Date.now())

  const handleStart = () => {

    countRef.current = setInterval(() => {
      setTimer((timer) => timer + 1);
    }, 1000);

    lastUpdatedRef.current = setInterval(() => {
      setLastUpdated(Date.now());
    }, 30000);
  };

现在我有一个 useEffect 每当 lastUpdated 作为依赖被触发时每 30 秒运行一个 calculate 函数:

  const firstCalculate = useRef(true);

  useEffect(() => {
    if (firstCalculate.current) {
      firstCalculate.current = false;
      return;
    }
    console.log("calculating");
    calculateModel();
  }, [lastUpdated]);

这会根据 lastUpdatedRef 每 30 秒更新一次 calculate 函数(00:30、01:00、01:30 等)。但是,我希望计时器从 lastUpdated 状态在其他地方被修改时重新启动(例如,如果 lastUpdated 在 00:08 被修改,下一次更新将是 00:38,01:08、01:38 等)。有办法吗?

基本上听起来您只需要另一个处理程序来清除并重新启动更新 lastUpdated 状态的 30 秒间隔。

示例:

const handleOther = () => {
  clearInterval(lastUpdatedRef.current);
  lastUpdatedRef.current = setInterval(() => {
    setLastUpdated(Date.now());
  }, 30000);
}

完整示例:

const calculateModel = () => console.log("calculateModel");

export default function App() {
  const countRef = React.useRef(null);
  const lastUpdatedRef = React.useRef(null);
  const [lastUpdated, setLastUpdated] = React.useState(Date.now());
  const [timer, setTimer] = React.useState(0);

  const handleStart = () => {
    countRef.current = setInterval(() => {
      setTimer((timer) => timer + 1);
    }, 1000);

    lastUpdatedRef.current = setInterval(() => {
      setLastUpdated(Date.now());
    }, 30000);
  };

  const handleOther = () => {
    clearInterval(lastUpdatedRef.current);
    lastUpdatedRef.current = setInterval(() => {
      setLastUpdated(Date.now());
    }, 30000);
  };

  const firstCalculate = React.useRef(true);

  React.useEffect(() => {
    if (firstCalculate.current) {
      firstCalculate.current = false;
      return;
    }
    console.log("calculating");
    calculateModel();
  }, [lastUpdated]);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>

      <div>Timer: {timer}</div>

      <button type="button" onClick={handleStart}>
        Start
      </button>
      <button type="button" onClick={handleOther}>
        Other
      </button>
    </div>
  );
}

不要忘记在卸载组件时清除任何 运行 间隔!

React.useEffect(() => {
  return () => {
    clearInterval(countRef.current);
    clearInterval(lastUpdatedRef.current);
  };
}, []);