设置功能后使用新状态

时间:2020-04-16 07:59:50

标签: javascript reactjs react-state

我可以在与更新状态相同的功能中使用更新状态吗? 在下面的示例中,我得到0。

使用useEffect,我可以在设置状态后立即访问新状态,但是如果要在函数中访问该怎么办。

作为附带的问题,当状态不直接与返回值连接时,是否可以使用状态?我应该改用道具吗?

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>
  )
}

2 个答案:

答案 0 :(得分:1)

您不能。这就是我使用useReducer的原因。

答案 1 :(得分:1)

不,你不能(或者也许可以,因为我会告诉你一些诡计)。对于功能组件,状态略有不同。当组件渲染时,将创建handleClick函数,并且由于JavaScript的工作方式,它会附加到该特定渲染的“作用域”。即使超时后,它仍然在旧的范围内。

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

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中?

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