react源码解析14.手写hooks
react源码解析14.手写hooks
视频讲解(高效学习):进入学习
往期文章:
1.开篇介绍和面试题
2.react的设计理念
3.react源码架构
4.源码目录结构和调试
5.jsx&核心api
6.legacy和concurrent模式入口函数
7.Fiber架构
8.render阶段
9.diff算法
10.commit阶段
11.生命周期
12.状态更新流程
13.hooks源码
14.手写hooks
15.scheduler&Lane
16.concurrent模式
17.context
18事件系统
19.手写迷你版react
20.总结&第一章的面试题解答
最关键的是要理解hook队列和update队列的指针指向和updateQueue的更新计算,详细见视频讲解
import React from "react";
import ReactDOM from "react-dom";
let workInProgressHook;
//当前工作中的hook
let isMount = true;
//是否时mount时const fiber = {//fiber节点
memoizedState: null,//hook链表
stateNode: App//dom
};
const Dispatcher = (() => {//Dispatcher对象
function mountWorkInProgressHook() {//mount时调用
const hook = {//构建hook
queue: {//更新队列
pending: null//未执行的update队列
},
memoizedState: null,//当前state
next: null//下一个hook
};
if (!fiber.memoizedState) {
fiber.memoizedState = hook;
//第一个hook的话直接赋值给fiber.memoizedState
} else {
workInProgressHook.next = hook;
//不是第一个的话就加在上一个hook的后面,形成链表
}
workInProgressHook = hook;
//记录当前工作的hook
return workInProgressHook;
}
function updateWorkInProgressHook() {//update时调用
let curHook = workInProgressHook;
workInProgressHook = workInProgressHook.next;
//下一个hook
return curHook;
}
function useState(initialState) {
let hook;
if (isMount) {
hook = mountWorkInProgressHook();
hook.memoizedState = initialState;
//初始状态
} else {
hook = updateWorkInProgressHook();
}let baseState = hook.memoizedState;
//初始状态
if (hook.queue.pending) {
let firstUpdate = hook.queue.pending.next;
//第一个updatedo {
const action = firstUpdate.action;
baseState = action(baseState);
firstUpdate = firstUpdate.next;
//循环update链表
} while (firstUpdate !== hook.queue.pending);
//通过update的action计算statehook.queue.pending = null;
//重置update链表
}
hook.memoizedState = baseState;
//赋值新的statereturn [baseState, dispatchAction.bind(null, hook.queue)];
//useState的返回
}return {
useState
};
})();
function dispatchAction(queue, action) {//触发更新
const update = {//构建update
action,
next: null
};
if (queue.pending === null) {
update.next = update;
//update的环状链表
} else {
update.next = queue.pending.next;
//新的update的next指向前一个update
queue.pending.next = update;
//前一个update的next指向新的update
}
queue.pending = update;
//更新queue.pendingisMount = false;
//标志mount结束
workInProgressHook = fiber.memoizedState;
//更新workInProgressHook
schedule();
//调度更新
}function App() {
let [count, setCount] = Dispatcher.useState(1);
let [age, setAge] = Dispatcher.useState(10);
return (
<>Clicked {count} times
【react源码解析14.手写hooks】Age is {age}
>
);
}function schedule() {
ReactDOM.render(, document.querySelector("#root"));
}schedule();
推荐阅读
- Android事件传递源码分析
- react|react 安装
- Quartz|Quartz 源码解析(四) —— QuartzScheduler和Listener事件监听
- Java内存泄漏分析系列之二(jstack生成的Thread|Java内存泄漏分析系列之二:jstack生成的Thread Dump日志结构解析)
- [源码解析]|[源码解析] NVIDIA HugeCTR,GPU版本参数服务器---(3)
- ffmpeg源码分析01(结构体)
- Android系统启动之init.rc文件解析过程
- Java程序员阅读源码的小技巧,原来大牛都是这样读的,赶紧看看!
- 小程序有哪些低成本获客手段——案例解析
- Vue源码分析—响应式原理(二)