React是在Fiber节点中保存的Hooks的状态的,通过Hooks的调用顺序找到对应状态,并在状态更新时触发对应组件的重新渲染.
Fiber节点
在React中,每个组件对应一个Fiber节点.简化的Fiber节点结构可以理解为:
const fiber = {
type: Counter,
memoizedState: null,//用来保存该函数组件的 Hooks 链表。
alternate: null,
// ...
};
memoizedState是用来保存该函数组件的 Hooks 链表。
其中链表的每个hook节点的结构可以简单理解为:
const hook = {
memoizedState: null, // 当前状态
baseState: null, // 基础状态
baseQueue: null, // 基础更新队列
queue: null, // 更新队列
next: null, // 下一个 Hook
};
React 主要依靠 Hooks 的调用顺序,而不是变量名来识别不同的 Hook。 React 按照顺序遍历 Hook 链表,从而找到对应状态。
这也解释了为什么 Hooks 不能放在条件语句中.
useState的底层实现原理
我们可以把useState分为两个阶段,首次渲染与更新
首次渲染
const [count, setCount] = useState(0);
React 会:
- 创建一个 Hook 节点。
- 将初始值
0保存到memoizedState。 - 创建状态更新队列。
- 返回当前状态和
dispatch函数。这里的dispatch就是我们熟悉的setCount。
更新
setCount(prev => prev + 1);
setCount(prev => prev + 1)
│
▼
创建 Update 对象
│
▼
加入 Hook 更新队列
│
▼
调度 Fiber 更新
│
▼
重新执行 Counter 函数
│
▼
处理更新队列,计算新状态
│
▼
生成新的 React 元素
│
▼
Reconciliation(协调)
│
▼
Commit(提交 DOM 更新)