使用react hooks设置状态,在什么情况下我必须传递一个函数来设置状态?

时间:2019-06-27 21:24:16

标签: reactjs react-hooks

这是我的代码:

function Tiker() {
  var [count, setCount] = useState(0);

  useEffect(() => {
    var timerID = setInterval(_=>
      setCount(count=>count+1)//setCount(count+1) wont work
    , 1000);

    return function cleanup() {
      clearInterval(timerID);
    };
  }, []);
  return <div>
      this is ticker   
      <button onClick={() => 
        setCount(count + 1)//setCount(count+1) does work
      }>up </button>
      {count}
      </div>
}

通过反复试验,我发现如果我从setinterval回调中使用setCount,则必须将回调传递给set状态,而不仅仅是传递值。

如果我通过onclick致电,情况并非如此。

那是为什么?

2 个答案:

答案 0 :(得分:2)

问题是useEffect的第二个参数

useEffect(() => {
    var timerID = setInterval(_=>
        setCount(count=>count+1)//setCount(count+1) wont work
    , 1000);

    return function cleanup() {
        clearInterval(timerID);
    };
}, []);

它是空数组([])。它为钩子定义了list of dependencies。因为它为空,这意味着钩子不依赖于任何状态或道具的值。因此,count变量在第一次调用useEffect时就被消耗掉了,而且保持陈旧状态。

要解决此问题,您应该完全删除useEffect的第二个参数,或者使数组包含[count]

回调正在工作,因为它接收先前的计数值作为第一个参数。

所以正确的代码看起来像

function Tiker() {
    var [count, setCount] = useState(0);

    useEffect(() => {
        var timerID = setInterval(_=>
            setCount(count + 1)
        , 1000);

        return function cleanup() {
            clearInterval(timerID);
        };
    }, [count]);  // Put variable that useHook depends on

    return <div>
        this is ticker   
        <button onClick={() => 
            setCount(count + 1) //setCount(count+1) does work
        }>up </button>
        {count}
    </div>
}

答案 1 :(得分:0)

从setInterval调用时,使用回调似乎是更改状态的最简单方法。正如Frodor的上述评论和https://overreacted.io/making-setinterval-declarative-with-react-hooks/

所表明的那样