首页 > 解决方案 > 反应状态没有正确更新

问题描述

我正在研究番茄钟,在休息后切换回番茄钟时遇到问题。

const start = () => {
    //this stop function clears the pre-existing timer if there is any.
    stop();

    setTimerOn(true);

    let interval = setInterval(() => {
      setDisplayTime((prev) => {

        //onBreak is false by default
        if (prev <= 0 && !onBreak) {
          setOnBreak(true);
          return breakDuration;
        }
        
        // this if statement is not being executed
        if (prev <= 0 && onBreak) {
          setOnBreak(false);
          return sessionDuration;
        }

        return prev - 1;
      });
    }, 1000);

    //save the timer insatance in react state
    setTimer(interval);
  }; 

每当计时器变为 0 时,我都会更新 onBreak 的状态。但是当我在反应开发工具中检查 onBreak 的状态时,只有首先执行块,然后状态永远不会改变。执行第一个 if 语句后,代码进入无限循环,只有 breakSession 被一遍又一遍地执行。

标签: javascriptreactjsreact-hooks

解决方案


您的代码的问题是您传递给的函数setInterval保存了onBreak它创建时的值;它无法获取当前状态onBreak。(我假设[onBreak, setOnBreak] = useState()。)

传递可变状态的一种方法是useRef. 像这样的东西:

const [onBreak, setOnBreak] = useState();

// Create a ref whose value is set automatically to onBreak
const onBreakRef = useRef();
useLayoutEffect(() => {
  onBreakRef.current = onBreak;
}, [onBreak]);

const start = () => {
    //this stop function clears the pre-existing timer if there is any.
    stop();

    setTimerOn(true);

    let interval = setInterval(() => {
      setDisplayTime((prev) => {

        if (prev <= 0 && !onBreakRef.current) {
          setOnBreak(true);
          return breakDuration;
        }
        
        if (prev <= 0 && onBreakRef.current) {
          setOnBreak(false);
          return sessionDuration;
        }

        return prev - 1;
      });
    }, 1000);

    //save the timer insatance in react state
    setTimer(interval);
};

这段代码虽然感觉很乱。您能否改为在对 when issetOnBreak(false)做出反应的其他代码中执行?然后代码可以无条件地当.onBreaktruesetIntervalsetOnBreak(true)prev <= 0


推荐阅读