2021-12-16

作者: buchila11 | 来源:发表于2021-12-16 12:18 被阅读0次

    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;//当前工作中的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;//第一个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-12-16

        本文链接:https://www.haomeiwen.com/subject/ldqvfrtx.html