第一章 JSX(React18源码解析一)
第二章 实现Virtual DOM(React18源码解析二)
第三章 根节点关联根Fiber(React18源码解析三)
第四章 初始化UpdateQueue、添加update(React18源码解析四)
第五章 实现时间切片函数和拷贝Fiber(React18源码解析五)
第六章 构建FiberTree(React18源码解析六)
第七章 commit(React18源码解析七)
第八章 React中的事件(React18源码解析八)
第九章 useReducer、useState(React18源码解析九)
第十章 React的dom diff(React18源码解析十)
第十一章 React的Effect(React18源码解析十一)
第十二章 React的同步、并发渲染(React18源码解析十二)
第十三章 React高优打断低优、饥饿问题(React18源码解析十三)
useReducer mount、update
在beginWork阶段遇到fiber.tag为FunctionComponent,调用renderWithHooks,在函数中根据1.是否有old fiber,2.有old fiber,根据fiber.memoizedState是否有值判断是mount阶段还是update阶段,不同阶段执行useReducer走不同函数,mount阶段走mountReducer、update阶段走updateReducer,在执行FunctionComponent时会调useReducer,及mountReducer或updateReducer
useReducer mount阶段
//会创建一个该useReducer的hook对象,并为每个hook创建一个queue用于存放每个hook的update,结构如下:
//hook:
{
memoizedState: "初始值",
queue: {
pending: "用循环链表把该hook的所有update串联起来,queue.pending指向last update,queue.pending.next指向first update",
dispatch: "及返回的setReducer",
},
next: "下一个hook,用单链表把该function component fiber的所有hooks串联起来,fiber.memoizedState为first hook",
}
const [hook.memoizedState,hook.queue.dispatch] = useReducer(reducer function,initVal)
//fiber hooks:
fiber.memoizedState=>FirstHook.next=>hook=>hook......
useReducer update阶段
执行setReducer及调mount阶段返回的hook.queue.dispatch,
内部会把setReducer({type:"xxx",payload:"xxx"})转成update,
及{action:{type:"xxx",payload:"xxx"},next:null}并缓存起来,
再重新render,因render是用schedule函数调用的,
而schedule及react切片函数,
此为异步函数相当于一个宏任务,
所以可以接着调用setReducer及多次setReducer批处理,
每次重新render时调finishQueueingConcurrentUpdates把update添加到hook.queue.pending,
重新render就要重新构建fiber tree,
当在beginWork阶段匹配到FunctionComponent时执行function,
function内部调useReducer(updateReducer)时也会采用如fiber般双缓冲技术,
根据old hook创建new hook,
因之前已把所有update添加到old hook的queue.pending上,
所以new hook上有所有的update,
使用useReducer的reducer函数遍历执行update得到newState,
此即useReducer update的过程
useState
1.基于useReducer
2.内部会对比oldState、newState,若相同返回不走schedule,不相同重新render
备注:
本文为清晰展现出本文核心逻辑把粘贴的源码中参数校验、typescript类型、不相关逻辑等已删除