useEffect意外触发

时间:2020-05-18 18:58:23

标签: javascript reactjs components jsx use-effect

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的依赖项数组中删除了计时器
  • 创建单独的函数以减少计时器

任何帮助将不胜感激。 ?

3 个答案:

答案 0 :(得分:1)

这是一个有效的示例,说明如何设置一次间隔,防止其变为负值并在卸载时清除它:

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>

答案 1 :(得分:0)

最适合我的解决方案:

 useEffect(() => {

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

    }, []);

我只是像上面那样更改了useEffect,即使其变成了useEffect的componentDidMount形式,现在可以正常使用了。

答案 2 :(得分:0)

从useEffect中删除“计时器”依赖项。

只要有时间,它将每次调用此函数