React学习-setState、useState
setState
语法:
this.setState(updater, [callback])
写法总结:
// 语法:this.setState({ newState })
this.setState({ count: 1 });
// 推荐使用,尤其是状态更新依赖于前一次状态时。它可以接收当前 state 和 props
// 语法:this.setState((state, props) => { return { newState } })
this.setState((state, props) => ({
count: state.count + 1
}));
// 在 setState 更新完成并重新渲染界面后执行,可确保获取到最新状态
this.setState({ count: 1 }, () => {
console.log('更新后的状态:', this.state.count);
});
特性:
-
setState是异步的:React 会将多个setState调用合并(batch)成一次更新,以提升性能。 - 在事件处理函数(如 onClick)中,
setState是批量的。 - 在原生事件、setTimeout、Promise 等异步上下文中,
setState可能不会自动批处理(但在 React 18+ 中已改进),可能表现为`同步状态。
⚠️ 注意:React 18 开始,无论在哪里调用
setState,默认都会自动批处理(automatic batching)。
底层原理(React 16+ Fiber 架构)
- 调用
setState会触发enqueueSetState。 - React 将更新放入一个更新队列(Update Queue) ,并标记该 Fiber 节点为“需要更新”。
- 在渲染阶段(render phase) ,React 会遍历 Fiber 树,收集所有待更新的节点。
- 在提交阶段(commit phase) ,应用 DOM 更新并触发副作用(如生命周期方法)。
关键点:
setState并不立即修改this.state,而是创建一个更新对象(update object),由 React 调度器(Scheduler)决定何时处理。
useState
它允许你向组件添加一个 状态变量,语法:
const [state, setState] = useState(initialState)
它没有回调函数;
特性:
- 和
setState一样,useState的setXXX也是异步且批量更新的。 - React 18 后,在任何上下文中(包括 setTimeout)都会自动批处理。
底层原理(Hooks 机制)
-
useState是 React Hooks 的一部分,其状态存储在 Fiber 节点的memoizedState字段中。 -
每个 Hook(如
useState,useEffect)在 Fiber 节点上按调用顺序形成一个链表(Hook 链表) 。 -
调用
setCount时,React 会:- 创建一个更新对象(类似类组件的 update)。
- 将其加入对应 Hook 的更新队列。
- 触发组件重新渲染(schedule update)。
-
在下一次渲染时,React 会遍历 Hook 链表,应用所有 pending updates,计算出新的 state。
📌 关键:Hooks 的状态与组件实例绑定,通过 Fiber 节点维持状态,而不是像类组件那样通过
this.state。
setState vs useState 对比
| 特性 |
setState(类组件) |
useState(函数组件) |
|---|---|---|
| 状态结构 | 单个对象(可包含多个字段) | 多个独立状态(每个 useState 管理一个) |
| 更新方式 | 合并对象(shallow merge) | 替换整个值(非合并) |
| 初始值 | 构造函数中定义 | useState(initialValue) |
| 底层存储 |
this.state(实际由 Fiber 管理) |
Fiber 的 memoizedState 链表 |
| 性能 | 批量更新,Fiber 调度 | 同左,支持并发模式 |
| 推荐使用 | 已逐渐被函数组件取代 | React 官方推荐方式 |
💡 注意:
useState不会自动合并对象!
底层共通机制(React 18+)
无论是 setState 还是 useState,最终都依赖于:
- Fiber 架构:每个组件对应一个 Fiber 节点,状态和更新都挂载其上。
- 更新队列(Update Queue) :存放待处理的状态变更。
- 调度器(Scheduler) :基于优先级(如用户交互高优先级)决定何时执行更新。
- 协调(Reconciliation) :通过 diff 算法生成最小 DOM 操作。
- 自动批处理(Automatic Batching) :React 18 起,所有状态更新默认批处理。