首页 > 解决方案 > 如何让 setState 在 setInterval 中工作?(目前正在工作)

问题描述

function func(){
  const [time, setTime] = useState(10);
  var timeRemaining = 10;
  const myInterval = setInterval(() => {
      if (timeRemaining > 0) {
        timeRemaining = timeRemaining - 1;
        setTime(timeRemaining);
      } else { clearInterval(myInterval) }
    }, 1000);
  return <div>{time}</div>
}

上面的代码由于变量timeRemaining. 但是,如果我删除该变量,它就会停止工作(为了保持代码干净):

const myInterval = setInterval(() => {
    if (time> 0) { setTime(time-1); } 
    else { clearInterval(myInterval); }
  }, 1000);

通过以上述方式重写它,它会停止更新time.

标签: javascriptreactjsreact-hookssetinterval

解决方案


使用 effects 来控制间隔,使用 ref 来保存对间隔计时器引用的引用,并使用功能状态更新来正确管理状态。

  • 效果 1 - 间隔效果的设置(挂载)和清理(卸载)
  • 效果 2 - 当时间到达 0 时清除间隔

功能组件代码:

function App() {
  const timerRef = useRef(null);
  const [time, setTime] = useState(10);

  useEffect(() => {
    // Use pure functional state update to correctly queue up state updates
    // from previous state time value.
    // Store returned interval ref.
    timerRef.current = setInterval(() => setTime(t => t - 1), 1000);

    // Return effect cleanup function
    return () => clearInterval(timerRef.current);
  }, []); // <-- Empty dependency array, effect runs once on mount.

  useEffect(() => {
    // Clear interval and nullify timer ref when time reaches 0
    if (time === 0) {
      clearInterval(timerRef.current);
      timerRef.current = null;
    }
  }, [time]); // <-- Effect runs on mount and when time value updates.

  return <div>{time}</div>;
}

编辑focused-mendeleev-2cezr


推荐阅读