写点什么

react 源码解析 14. 手写 hooks

用户头像
全栈潇晨
关注
发布于: 2021 年 06 月 17 日

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.总结&第一章的面试题解答


21.demo


最关键的是要理解 hook 队列和 update 队列的指针指向和 updateQueue 的更新计算,详细见视频讲解


import React from "react";import ReactDOM from "react-dom";
let workInProgressHook;//当前工作中的hooklet 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;//第一个update
do { const action = firstUpdate.action; baseState = action(baseState); firstUpdate = firstUpdate.next;//循环update链表 } while (firstUpdate !== hook.queue.pending);//通过update的action计算state
hook.queue.pending = null;//重置update链表 } hook.memoizedState = baseState;//赋值新的state
return [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.pending
isMount = false;//标志mount结束 workInProgressHook = fiber.memoizedState;//更新workInProgressHook schedule();//调度更新}
function App() { let [count, setCount] = Dispatcher.useState(1); let [age, setAge] = Dispatcher.useState(10); return ( <> <p>Clicked {count} times</p> <button onClick={() => setCount(() => count + 1)}> Add count</button> <p>Age is {age}</p> <button onClick={() => setAge(() => age + 1)}> Add age</button> </> );}
function schedule() { ReactDOM.render(<App />, document.querySelector("#root"));}
schedule();
复制代码


发布于: 2021 年 06 月 17 日阅读数: 6
用户头像

全栈潇晨

关注

还未添加个人签名 2021.02.17 加入

还未添加个人简介

评论

发布
暂无评论
react源码解析14.手写hooks