React 状态未正确更新

时间:2021-07-05 12:09:53

标签: javascript reactjs react-hooks

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

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 的状态。但是当我在 React 开发工具中检查 onBreak 的状态时,只有在执行块时才首先更新状态,然后状态永远不会改变。代码在执行第一个 if 语句后进入无限循环,只有 breakSession 被一遍又一遍地执行。

1 个答案:

答案 0 :(得分:0)

您的代码的问题在于您传递给 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);
};

虽然这段代码感觉很乱。您能否在其他代码中执行 setOnBreak(false) 来响应 onBreaktrue?然后 setInterval 代码可以在 setOnBreak(true) 时无条件地prev <= 0