首页 > 解决方案 > 使用反应钩子设置状态,在什么情况下我必须传递一个函数来设置状态?

问题描述

这是我的代码:

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,我必须将回调传递给设置状态,而不仅仅是值。

如果我从 onclick 调用,情况并非如此。

这是为什么?

标签: reactjsreact-hooks

解决方案


问题是第二个论点useEffect

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

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

它是空数组 ( [])。它定义了挂钩的依赖项列表。因为它是空的,这意味着钩子不依赖于任何状态或道具的值。所以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>
}

推荐阅读