import { useState } from 'react'
function App() {
const [age, setAge] = useState(16)
const [isAdult, setIsAdult] = useState(false)
function growUp() {
setAge(prev => prev + 1)
if (age === 18) setIsAdult(true)
}
return (
<div>
{isAdult && <p>Adult</p>}
<button onClick={growUp}>grow up</button>
<p>{age}</p>
</div>
)
}
export default App
上面一段代码中的<p>Adult</p>不会在age达到18立即显示,而是在19的时候显示
在growUp函数前面加个async,setAge前面加个await也没有用
如果不用函数组件和useState,用class组件和setState结果也一样
要用useEffect才行:
import { useEffect, useState } from 'react'
function App() {
const [age, setAge] = useState(16)
const [isAdult, setIsAdult] = useState(false)
function growUp() {
setAge(prev => prev + 1)
}
useEffect(() => {
if (age === 18) setIsAdult(true)
}, [age])
return (
<div>
{isAdult && <p>Adult</p>}
<button onClick={growUp}>grow up</button>
<p>{age}</p>
</div>
)
}
export default App
stack overflow 上面一篇是这样解释的:
Much like setState in Class components created by extending React.Component
or React.PureComponent
, the state update using the updater provided by useState
hook is also asynchronous, and will not be reflected immediately.
Also, the main issue here is not just the asynchronous nature but the fact that state values are used by functions based on their current closures, and state updates will reflect in the next re-render by which the existing closures are not affected, but new ones are created. Now in the current state, the values within hooks are obtained by existing closures, and when a re-render happens, the closures are updated based on whether the function is recreated again or not.
If async was the only reason, it would be possible to await setState()
.
However, both props
and state
are assumed to be unchanging during 1 render.
Treat
this.state
as if it were immutable.
With hooks, this assumption is enhanced by using constant values with the const
keyword:
也就是说state在每一次渲染中是不变的,要等到下次渲染才改变