在下面的代码段中,当我单击“更改”按钮以更改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)
答案 0 :(得分:2)
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>
答案 1 :(得分:0)
这是预期的行为。您可能要使用useEffect
来访问最新值。
以下是讨论相同问题的主题:useState set method not reflecting change immediately
希望这会有所帮助!
答案 2 :(得分:0)
状态和挂钩是异步的。调用isLoading
之后,您不会直接在set...
中看到任何更改,而只会在组件的下一次渲染时看到,这将“很快”发生。
如果您确实打印了statelet的值(作为字符串; false
不显示任何内容),您可以看到更改:
return (
<div>
<button onClick={buttonHandler} type="button">
Change (now {"" + isLoading})
</button>
</div>
)