React:ClearInterval 并立即重新开始

Posted

技术标签:

【中文标题】React:ClearInterval 并立即重新开始【英文标题】:React: ClearInterval and Immediately Start Again 【发布时间】:2021-11-07 23:46:26 【问题描述】:

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


  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 秒(00:30、01:00、01:30 等)更新 calculate 函数。但是,我希望计时器在 lastUpdated 状态在其他地方被修改时重新启动(例如,如果 lastUpdated 在 00:08 被修改,下一次更新将是 00:38、01:08、01:38 等) .有没有办法做到这一点?

【问题讨论】:

旁注:Dan Abramov 的article on setInterval in useEffect 读起来很有趣。 【参考方案1】:

基本上听起来您只需要另一个处理程序来清除并重新启动更新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);
  ;
, []);

【讨论】:

以上是关于React:ClearInterval 并立即重新开始的主要内容,如果未能解决你的问题,请参考以下文章

重新渲染 Reactjs 后,父组件立即失去状态

React.js/Redux:Reducers 中的 setInterval 和 clearInterval

API 更改后重新渲染 React 组件

React 60s倒计时

js清除定时器

在useState中获得[react [duplicate]]后立即获取值]