1. 程式人生 > 其它 >實驗三-電子公文傳輸系統1-個人貢獻

實驗三-電子公文傳輸系統1-個人貢獻

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();