【问题标题】:useState with boolean value in react反应中具有布尔值的useState
【发布时间】:2020-04-06 06:42:04
【问题描述】:

在下面的代码 sn-p 中,当我单击更改按钮更改 isLoading 的值时, 什么也没发生(isLoading 是假的)。

const App = (props) => {
  const [isLoading, setIsLoading] = useState(false)

  const buttonHandler = () => {
    setIsLoading(current => !current)
    console.log(isLoading) // is false 
  }

  return (
    <div>
      <button onClick={buttonHandler} type="button">
        Change
      </button>
    </div>
  )
}

我尝试通过以下方式更改isLoading但不影响:

1-setIsLoading(current => !current)
2-setIsLoading(!isLoading)
3-setIsLoading(true)

【问题讨论】:

  • 状态改变是异步的,所以你不能在下一行console.log他们看到他们改变了。在 useState 行下方尝试 printg isLoading,这样当组件以新状态重新渲染时,它将打印出来
  • 这个问题几乎每天都会被问到。请在询问之前搜索 SO。这回答了你的问题了吗? React setState not updating state
  • 状态更改是异步的。所以使用开发者工具中的组件标签来监控状态变化。

标签: reactjs react-hooks


【解决方案1】:

setIsLoading 是异步函数,更新后无法立即获取状态值。

setState 操作是异步的,并且为了提高性能而进行批处理。 setState() 不会立即改变它。因此,setState 调用是异步的,并且是批处理的,以获得更好的 UI 体验和性能。这适用于两个functional/Class 组件。

来自 React 文档

React 可以将多个 setState() 调用批处理到单个更新中以提高性能。 因为 this.props 和 this.state 可能会异步更新,所以你不应该依赖它们的值来计算下一个状态。 你可以阅读更多关于这个here

如果您想获取更新后的状态值,请使用 useEffect 挂钩和依赖数组。 React 会在每次状态更新后执行这个钩子。

const {useEffect, useState } = React;

const App = (props) => {
  const [isLoading, setIsLoading] = useState(false)
  const buttonHandler = () => {
    setIsLoading(current => !current)
  }

  useEffect( () => {
    console.log(isLoading);
}, [isLoading]);

  return (
    <div>
      <button onClick={buttonHandler} type="button">
        Change
      </button>

      {isLoading? "Loading...": null}
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('root'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>

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

【讨论】:

    【解决方案2】:

    这是预期的行为。您可能希望使用useEffect 访问最新值。

    这是一个讨论同一问题的线程:useState set method not reflecting change immediately

    希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      状态和钩子是异步的。在调用 set... 之后,您不会直接看到 isLoading 的变化,而只会在组件的下一次渲染时看到,这将“很快”发生。

      如果您打印 statelet 的值(作为字符串;false 呈现为空),您可以看到更改:

      return (
          <div>
            <button onClick={buttonHandler} type="button">
              Change (now {"" + isLoading})
            </button>
          </div>
        )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-03-16
        • 1970-01-01
        • 2020-12-14
        • 2021-07-17
        • 2017-12-23
        • 2021-10-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多