//是否是第一次加载
let isMount = true;
//fiber 链表指针
let workInProgressHook = null;
//每个组件对应一个fiber对象
let fiber = {
//保存组件函数
stateNode:App,
//保存组件对应的hooks 数据链表
memoizedState:null
}
function useState(initialState){
//生成一个hook 对象
let hook;
if(isMount){
//第一次加载初始化hook对象
hook = {
memoizedState:initialState,
next:null,
queue:{
pending:null
}
}
//当是第一个useState的时候
if(!fiber.memoizedState){
fiber.memoizedState = hook;
}else{
//挂在到最后一个
workInProgressHook.next = hook;
}
//移动指针到最后一个
workInProgressHook = hook;
}else{
//更新,非第一次加载
//设置当前hook对象
hook = workInProgressHook;
//指针后移
workInProgressHook = hook.next;
}
//获取hook对应的值
let baseState = hook.memoizedState;
//需要更新,环状链表遍历
if(hook.queue.pending){
// 获取update环状单向链表中第一个update
let firstUpdate = hook.queue.pending.next;
do {
// 执行update action
const action = firstUpdate.action;
baseState = action(baseState);
firstUpdate = firstUpdate.next;
// 最后一个update执行完后跳出循环
} while (firstUpdate !== hook.queue.pending.next);
}
//重新给hook 赋值
hook.memoizedState = baseState;
return [baseState,dispatchAction.bind(null,hook.queue)]
}
//memoizedState更新方法
function dispatchAction(queue,action){
//创建要更新的链表(环状)
const update = {
action:action,
next:null
}
//与当前hook的操作对象queue关联
//当前hook没有更新
if(!queue.pending){
//u0 -> u0
update.next = update;
}else{
//u1 -> u0 ->u1
update.next = queue.pending.next;
queue.pending.next = update;
}
queue.pending = update;
//模拟调度
schedule();
}
//初始化调度render函数
function schedule(){
//指针指到第一个节点
workInProgressHook = fiber.memoizedState;
isMount = false;
//触发组件render
fiber.stateNode();
}
function App(){
const [num,updateNum] = useState(0);
const [num1,updateNum1] = useState(1);
console.log(num,num1);
return {
click:()=>{
updateNum(num=>num+1);
}
}
}
var test = App();
test.click();
模拟实现hook useState
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
推荐阅读更多精彩内容
- 模拟useState 要点 _下划线代表内部的变量 const currentIndex = _index; 缓存...
- 背景 React 16.8 引入了 Hook[https://zh-hans.reactjs.org/docs/h...
- const [text, setText] = useState(0);初始化text=0;setText是唯一能...