0

下面是一个使用useState(). 它工作正常,除非+单击按钮,然后数字可以交替出现70017000然后在一些数字之间快速闪烁。

实际上,在不点击 的情况下+,该数字表现良好,但最高可达 8000 或 9000 左右,然后它可能会开始在某些数字之间闪烁。为什么会这样,如何解决?

PS初步调试发现是:好像Counter()被调用了多次,每次都设置了一个Interval Timer。所以“神奇地”,似乎useState()只运行了一次——出于某种未知和神奇的原因——或者它运行了不止一次,但每次都返回完全相同的内容,因为某种神奇的机制。0第一次真的是这样的初始值。当它在useState(0)未来的时候,count不是0......我们不想要那个,但它也不是那么实用(就像在数学函数中一样)。

function Counter() {
    const [count, setCount] = React.useState(0);

    setInterval(() => {
        setCount(count + 1000);
    }, 1000);

    return (
        <div>
            <button onClick={() => setCount(count + 1)}> + </button>                    
            { count }
            <button onClick={() => setCount(count - 1)}> - </button> 
        </div>
    );
}

ReactDOM.render(<Counter />, document.querySelector("#root"));
button { margin: 0 1em }
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>

<div id="root"></div>

4

2 回答 2

6
  1. 每次重新渲染组件时,都会执行功能组件中的代码。因此,在每次重新渲染时,您都将启动一个无限计时器,该计时器每秒增加 1000 来计数
  2. 每次你改变组件的状态时,React 都会重新渲染它。意思是,每次执行都会setCount导致新的重新渲染并启动新的计时器
  3. 此外,setCount它是异步的,如果您需要依赖先前的状态来确定下一个状态,您应该使用回调调用,就像在其他答案 ( setCount(c => c + 1))中演示的那样

像这样的东西应该起作用:

import React, {useState, useRef, useEffect} from 'react';

function Counter() {
    const [count, setCount] = useState(0);
    //useRef gives us an object to store things between re-renders
    const timer = useRef();

    useEffect(() => {
      timer.current = setInterval(() => {
        setCount(count => count + 1000);
      }, 1000);

      //If we return a function, it will be called when component is dismounted
      return () => {
        clearInterval(timer.current);
      }
    }, []);

    return (
        <div>
            <button onClick={() => setCount(count => count + 1)}> + </button>                    
            { count }
            <button onClick={() => setCount(count => count - 1)}> - </button> 
        </div>
    );
}
于 2020-02-13T02:57:21.243 回答
1

不太确定“为什么会这样”,但可以通过替换setCount(c => c + 1)按钮和setCount(c => c + 1000)间隔来解决。

将“setInterval”放入效果中还可以确保只有一个间隔......

  React.useEffect(() => {  
     setInterval(() => {
        setCount(c => c + 1000);
     }, 1000);
  },[])

PS Counter()在每次渲染时都会被调用,我认为......而useState每次安装时只会被设计调用一次。

于 2020-02-13T02:51:56.920 回答