设置后在函数中使用新状态

Using new state in a function after setting it

我可以在更新状态的同一函数中使用更新状态吗? 在下面的示例中,我得到 0.

使用useEffect我可以在设置状态后立即访问新状态,但是如何在函数中访问它?

作为附带问题,我可以(或应该)在状态与 return 中的内容不直接相关的情况下使用该状态吗?我应该改用道具吗?

function App() {
  const [count, setCount] = useState(0)

  const handleClick = async () => {
    setCount(count => (count + 1));
    await new Promise(r => setTimeout(r, 2000));
    console.log(count); // I get 0
  }

  return (
    <div>
      <Button onClick={handleClick}></Button>
    </div>
  )
}

你就是做不到。这就是我使用 useReducer 的原因。

不,你不能(或者你可以用一点小技巧,我会告诉你)。对于功能组件,状态有点不同。您的 handleClick 函数在组件呈现时创建,并且由于 JavaScript 的工作方式,它会附加到该特定呈现的 "scope"。即使在超时之后,它仍然在那个旧范围内。

解决这个问题的一种方法是使用参考。

function App() { 
    const [count, setCount] = useState(0)

    const countRef = useRef(count)
    countRef.current = count

    const handleClick = async () => {
        setCount(count => (count + 1)); 
        await new Promise(r => setTimeout(r, 2000)); 
        console.log(countRef.current); 
    } 

    return ( 
        <div>
            <Button onClick={handleClick}></Button>
        </div>
    )
}

这将在重新呈现组件时更新引用。此更新将更改所有引用,甚至是旧范围中的引用。

然而,我经常使用 React,而且我确信在实践中我从未被要求使用它。我会说这是不好的做法:即使有超时,你也不能 100% 确定状态实际上有足够的时间来更新,所以这可能会导致奇怪的错误。为什么你真的想要这样做?例如,您不能将需要新状态的代码放在 useEffect 中吗?

至于附带问题:当状态发生变化时需要重新渲染组件时,您应该使用状态。如果您不希望您的组件在状态更改时重新渲染,您应该使用另一种存储数据的方法(例如 refs)。