作为一个React Hook,它只能在组件的顶层调用
语法
useState(initialState)
initialState
:state的初始值。当传递函数作为initialState时,它将被视为初始化函数,它应该是一个纯函数,不应该传入任何参数,并且应该返回一个值来作为初始值。此参数只有在初始化渲染时使用,在之后将被忽略
useState
返回一个数组:状态变量 和 状态设置(set)函数
按照惯例,使用解构赋值的方法来命名状态和状态设置函数,例如const [x, setX] = useState(0)
set
函数
通过调用set
函数来更新状态变量的值,你可以:
- 传入一个不同的新值,例如:
setName('cqy')
- 基于待定的
state
来计算新的状态(更新函数),例如:setAge(a => a + 1)
当将函数作为参数传递给
set
函数时,它被视为更新函数。它必须是纯函数,唯一的参数是待定的state
,并应该返回下一个状态
注意事项
set
函数仅更新 下一次 渲染的状态变量,如果在调用set
函数后立刻读取状态便了,得到的仍然是渲染在屏幕上的旧值。
待定的state
下面的例子中,我们希望在点击之后将count增加3,但结果是count只会增加1。
原因就在于,前一个set
函数执行完后,后一个set
函数读取的仍然是旧的状态,React会批量处理状态更新,在所有事件处理函数运行并调用其set
函数后更新屏幕。所以在页面重新渲染前,获取到的仍然是旧值
1 | export default function Counter() { |
为了解决这个问题,可以给set
函数传递一个更新函数,它可以根据**最新的state
**(即待定的state
,可以理解为若没有后续改变state的操作,该state将会在下一次渲染时被使用)状态来计算更新下一个state
状态
1 | function handleClick() { |
更新状态中的对象和数组
当把对象和数组作为状态变量时,你应该替换它而不应该单纯的改变对象中的某个属性或者数组中的某项
示例代码:
1 | const [obj, setObj] = useState({ |
避免重复创建初始状态
React只在初次渲染时保存初始状态,后续渲染都会忽略
1 | function App() { |
尽管createInitialX()
的结果仅用于初次渲染,但是每次重新渲染时都要调用此函数,如果它的执行需要昂贵的计算,会导致资源浪费
为了解决这个问题,你应该把函数本身作为初始化函数传递给useState
,而不是调用该函数
1 | const [ x, setX ] = useState(createInitialX) //合理的实践 |