useState 实现原理
📖 本节总结
useState 通过链表存储状态,每次渲染根据渲染次数获取对应的状态。
数据结构
Hooks 链表
javascript
// 每个 useState 创建一个 Hook 节点
const hook = {
memoizedState: null, // 保存的状态
baseQueue: null, // 基础队列
queue: null, // 更新队列
next: null // 指向下一个 Hook
}
// fiber.memoizedState 指向第一个 Hook
fiber.memoizedState = firstHook1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
useState 实现
javascript
function useState(initialState) {
// 获取当前的 Hook
const hook = mountWorkInProgressHook()
// 初始值
if (typeof initialState === 'function') {
hook.memoizedState = initialState()
} else {
hook.memoizedState = initialState
}
// dispatch 函数
const queue = {
pending: null,
dispatch: dispatchAction.bind(null, hook)
}
hook.queue = queue
// setState
const dispatch = (action) => {
const nextState = typeof action === 'function'
? action(hook.memoizedState)
: action
hook.memoizedState = nextState
// 触发更新
scheduleUpdate()
}
return [hook.memoizedState, dispatch]
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
更新流程
javascript
// setState(1)
dispatch(1)
↓
放入 updateQueue
↓
触发 scheduleUpdate
↓
重新渲染组件
↓
获取到新的状态1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
批量更新
javascript
// React 18 自动批量更新
setCount(1)
setName('a')
setAge(25)
// 只触发一次渲染!1
2
3
4
5
2
3
4
5
总结
| 概念 | 说明 |
|---|---|
| Hooks 链表 | 每个 Hook 连接成链表 |
| memoizedState | 保存状态值 |
| queue | 更新队列 |
| 批量更新 | 合并多次 setState |