【问题标题】:How to use setInterval in react?如何在反应中使用 setInterval?
【发布时间】:2020-04-24 13:35:02
【问题描述】:

我正在尝试为打字游戏制作一个简单的 setInterval 函数,但它会根据我的语法不断出现故障,或者像现在这样根本没有更新。

如何让它每秒更新一次并调用 if 语句中的函数?

const [counter, setCounter] = useState(10);

useEffect(() => {
  let timer = setInterval(() => {
    setCounter(counter - 1);

    if (counter === 0) {
      setWordIndex(wordIndex + 1);
      setLives(lives - 1);
      life.play();
      setCounter(10);
    }
  }, 1000);
}, []);

*********编辑***************

这就是我现在所拥有的。第一个答案解决了计数器不递减的异步问题,但我不得不将 if 语句移到 useEffect 之外,以纠正我认为是由同样的问题引起的。

 useEffect(() => {
    let timer = setInterval(() => {
      setCounter( counter => counter - 1);
    }, 1000);
  }, []);
  if (counter == 0) {
    setWordIndex(wordIndex + 1);
    setLives(lives - 1);
    life.play();
    setCounter(10);
  }

【问题讨论】:

标签: javascript reactjs settimeout setinterval use-effect


【解决方案1】:

setCounter 函数中使用回调函数。当您在异步函数中调用状态更新时。最好根据之前的状态更新状态。

const [counter, setCounter] = useState(10);
useEffect(() => {
    let timer = setInterval(() => {
        setCounter(counter => {
            const updatedCounter = counter - 1;
            if (updatedCounter === 0) {
                setWordIndex(wordIndex + 1);
                setLives(lives - 1);
                life.play();
                return 10;
            }
            return updatedCounter;
        }); // use callback function to set the state

    }, 1000);
    return () => clearInterval(timer); // cleanup the timer
}, []);

【讨论】:

  • 感谢我的计数器现在已完美更新,但是当计数达到 0 时我的 if 语句函数没有触发。有什么想法吗?再次感谢!
  • 想通了!由于同样的异步问题,我不得不将 if 语句移到 useEffect 之外。谢谢!
  • @dnolan 如果将它移到 useEffect 之外,它将刷新两次。这个答案也容易出现内存泄漏。看我的回答。
  • 使用状态更新和内部的逻辑,所以它只会在状态改变时运行。但不要在状态中更新状态。
  • @Sohail 即使您复制了我的答案,您仍然犯了一个错误。正在修复它...
【解决方案2】:

之前的答案没有考虑其他状态 - wordIndex 和生活,并且不包括明确的间隔

建议在 setIntervals 中使用回调 setState 并在下次调用 useEffect 时清除间隔

  const [counter, setCounter] = React.useState(10);
  React.useEffect(() => {
    let timer = setInterval(() => {
      // It's advisable to use callback setState inside setIntervals
      setCounter(prev => {
        if (prev !== 0) return prev - 1;

        setWordIndex(wordIndex + 1);
        setLives(lives - 1);
        life.play();    
        return 10;
      });
    }, 1000);

    // And clear the interval next useEffect call
    return () => clearInterval(timer);
  }, [wordIndex, lives]);

【讨论】:

    【解决方案3】:

    之前的答案没有考虑计数器值不会立即更新。由于未清除 setInterval,因此它们也容易发生内存泄漏。

    const [counter, setCounter] = useState(10);
    useEffect(() => {
      let timer = setInterval(() => {
        setCounter( counter => {
            const nC = counter - 1;
            if (nC === 0) {
               setWordIndex(wordIndex + 1);
               setLives(lives - 1);
               life.play();
               return 10;
            }
            return nC;
         });
      }, 1000);
      return () => clearInterval(timer);
    }, []);
    

    【讨论】:

      猜你喜欢
      • 2021-06-02
      • 2021-10-03
      • 2020-09-10
      • 2019-09-09
      • 2021-11-05
      • 2021-04-05
      • 2021-07-31
      • 1970-01-01
      • 2020-12-09
      相关资源
      最近更新 更多