useEffect 被意外触发

useEffect is trigged unexpectedly

意外调用了 useEffect 挂钩。一旦计时器达到零并且当我将其设置为 10(使用重新发送 Otp 按钮)时,计时器开始减少的速度快于 1 秒。

我的组件如下:

const EnterOtpView = ({ touched, errors, isSubmitting }) => {
    const [timer, setTimer] = useState(3);

    useEffect(() => {
        if (timer > 0) {
            setInterval(() => setTimer((prevTimer) => prevTimer - 1), 1000);
        }
    }, [timer]);

    return (
        <div>

                {timer > 0 ? (
                    <p>Resend Otp in: {timer} seconds</p>
                ) : (
                    <button
                        type='button'
                        className='btn btn-link'
                        onClick={() => setTimer(10)}
                    >
                        resend otp
                    </button>
                )}
        </div>
    );
};


我尝试过的:

如有任何帮助,我们将不胜感激。

对我有用的解决方案:

 useEffect(() => {

            setInterval(() => setTimer((prevTimer) => prevTimer - 1), 1000);

    }, []);

我只是像上面那样改变了 useEffect,即将它变成了 useEffect 的 componentDidMount 形式,现在它可以正常工作了。

从 useEffect 中删除 "timer" 依赖项..

每次都会调用这个函数

这是一个工作示例,说明如何设置一次间隔,防止它变为负数,并在卸载时清除它:

const {useState, useEffect} = React;

const Example = () => {
  const [timer, setTimer] = useState(3);

  useEffect(() => {
    // setInterval returns the id of the interval so we can clear it later
    const id = setInterval(() => {
      setTimer((prevTimer) => {
        // Move our negative logic inside the functional update
        if (prevTimer > 0) {
          return prevTimer - 1;
        }
        return 0;
      })}, 1000);
    
    // Clear the interval on umount
    return () => {
      clearInterval(id);
    }
  }, []);

  return (
    <div>
      {timer > 0 ? (
        <p>Resend Otp in: {timer} seconds</p>
      ) : (
        <button
          type='button'
          className='btn btn-link'
          onClick={() => setTimer(10)}
        >
          resend otp
        </button>
      )}
    </div>
  );
}

ReactDOM.render(<Example />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>