useState用法
useState
是用来管理状态的hook
1. 用法
const [state, setState] = useState(initialState);
- 参数
useState
接收一个参数,如果这个参数是值,那么这个值则会直接作为state的初始值,如果这个值为函数,则函数的结果会就是state
的初始值。
const [count, setCount] = useState(0) // count 的初始值为0
- 返回值
该hook返回一个数组,第一项为初始状态state
,第二项为一个状态更新函数setState
,在使用时通过这个函数来修改state
的值。
import { useState } from 'react'
function App() {
const [count, setCount] = useState(0)
// 增加count的值
const handleAddCount = () => {
setCount(count + 1)
}
// 减少count的值
const handleMinusCount = () => {
setCount(count - 1)
}
return (
<div className="app">
<h1>Hello React UseState</h1>
<button onClick={handleAddCount}>+</button>
{count}
<button onClick={handleMinusCount}>-</button>
</div>
)
}
export default App
当调用setCount()
的时候,count
被改变,即状态被改变,而这种状态改变的方式就会引起视图的更新,所以我们可以在页面上观测到最新值。但如果不使用useState
,使用普通变量,那么变量值改变后,视图也不会被更新。
2. useState
的参数
在使用useState
的时候,可以直接传递简单类型,如上面的例子,当我们要操作对象的状态的时候,则需要通过如下的方式进行修改。不要直接去修改state
。
import { useState } from 'react'
function App() {
const [studentsInfo, setStudentsInfo] = useState([
{
name: 'paul',
age: 23,
},
])
const handleAddStudent = () => {
// 正确的做法
setStudentsInfo([...studentsInfo, { name: 'xiaoxin', age: 20 }])
// 错误的做法
// setStudentsInfo(studentsInfo.push({
// name: 'xiaoxin',
// age:25
// }))
}
return (
<div className="app">
<h1>Hello React UseState</h1>
<ul>
{studentsInfo.map((item) => (
<li key={item.name}>
{item.name} ----- {item.age}
</li>
))}
</ul>
<button onClick={handleAddStudent}>点我修改学生信息</button>
</div>
)
}
export default App
useState
还可以传递一个函数,那么返回值就是count
的初始值
const [count, setCount] = useState(() => 1)
当组件重新渲染的时候,useState
不会重新渲染,这样才能使得页面总是获得到新的值,当我们在传递一个函数作为useState
参数的时候,虽然仅仅是将函数计算结果返回,但是注意我们要传递函数本身,如:useState(fn)
,而不是传递useState(fn())
,如果以后者方式传递,fn()
则会在每次组件重新渲染的时候重新执行,从而造成性能浪费。
3. setCount
的参数
setCount
可以直接改变state
,也可以接收一个函数
const [count, setCount] = useState(0)
const handleAddCount = () => {
setCount(count + 1)
setCount(count + 1)
setCount(count + 1)
}
当执行这段代码的时候,我们希望的结果是,点击按钮,count
能够增加3,然而,结果确是增加了1
。这是因为react会批量修改状态修改信息,如果更新一次,组件更新一次,那么随着修改次数的增加,性能将会受到大大的影响。而当同步进行修改时,最后的setCount(count+1)
会对前面的状态进行覆盖。要得到正确的结果,则需要为setCount
传递一个回调函数,当参数为函数时,React会将他们放在队列中,然后依次执行,从而确保下次setCount
是对最新的count
值进行操作。
const [count, setCount] = useState(0)
const handleAddCount = () => {
setCount(() => count + 1)
setCount(() => count + 1)
setCount(() => count + 1)
}
这样就会获取到正确的结果了。
4. 状态更新的时机
const [count, setCount] = useState(0)
const handleAddCount = () => {
console.log(count); // 0
setCount(count + 10)
console.log(count); // 0
setTimeout(() => {
console.log(count); // 0
}, 5000)
}
当使用setCount
的时候,组件的渲染不是直接发生的,而是等函数执行完毕后再进行更新,而状态的更新又会引起组件的渲染,所以,虽然执行了setCount()
,但是在当前组件下,count
的值并未发生改变,所以此时count
的值全部为0。
5.注意事项
如果要使用Hook,那么需要注意以下几点:
- 只能在顶层使用,即在你需要使用之间进行声明。
- 只能在React组件中使用。
- 不能在
if
、while
、函数中使用钩子,参考第一条。
如有不妥之处,欢迎指出,相互学习,共同进步。