react源碼解析14.手寫hooks
視頻課程(高效學(xué)習(xí)):進(jìn)入課程
課程目錄:
6.legacy和concurrent模式入口函數(shù)
最關(guān)鍵的是要理解hook隊(duì)列和update隊(duì)列的指針指向和updateQueue的更新計(jì)算痒钝,詳細(xì)見視頻講解
import React from "react";
import ReactDOM from "react-dom";
let workInProgressHook;//當(dāng)前工作中的hook
let isMount = true;//是否時(shí)mount時(shí)
const fiber = {//fiber節(jié)點(diǎn)
memoizedState: null,//hook鏈表
stateNode: App//dom
};
const Dispatcher = (() => {//Dispatcher對象
function mountWorkInProgressHook() {//mount時(shí)調(diào)用
const hook = {//構(gòu)建hook
queue: {//更新隊(duì)列
pending: null//未執(zhí)行的update隊(duì)列
},
memoizedState: null,//當(dāng)前state
next: null//下一個(gè)hook
};
if (!fiber.memoizedState) {
fiber.memoizedState = hook;//第一個(gè)hook的話直接賦值給fiber.memoizedState
} else {
workInProgressHook.next = hook;//不是第一個(gè)的話就加在上一個(gè)hook的后面秒拔,形成鏈表
}
workInProgressHook = hook;//記錄當(dāng)前工作的hook
return workInProgressHook;
}
function updateWorkInProgressHook() {//update時(shí)調(diào)用
let curHook = workInProgressHook;
workInProgressHook = workInProgressHook.next;//下一個(gè)hook
return curHook;
}
function useState(initialState) {
let hook;
if (isMount) {
hook = mountWorkInProgressHook();
hook.memoizedState = initialState;//初始狀態(tài)
} else {
hook = updateWorkInProgressHook();
}
let baseState = hook.memoizedState;//初始狀態(tài)
if (hook.queue.pending) {
let firstUpdate = hook.queue.pending.next;//第一個(gè)update
do {
const action = firstUpdate.action;
baseState = action(baseState);
firstUpdate = firstUpdate.next;//循環(huán)update鏈表
} while (firstUpdate !== hook.queue.pending);//通過update的action計(jì)算state
hook.queue.pending = null;//重置update鏈表
}
hook.memoizedState = baseState;//賦值新的state
return [baseState, dispatchAction.bind(null, hook.queue)];//useState的返回
}
return {
useState
};
})();
function dispatchAction(queue, action) {//觸發(fā)更新
const update = {//構(gòu)建update
action,
next: null
};
if (queue.pending === null) {
update.next = update;//update的環(huán)狀鏈表
} else {
update.next = queue.pending.next;//新的update的next指向前一個(gè)update
queue.pending.next = update;//前一個(gè)update的next指向新的update
}
queue.pending = update;//更新queue.pending
isMount = false;//標(biāo)志mount結(jié)束
workInProgressHook = fiber.memoizedState;//更新workInProgressHook
schedule();//調(diào)度更新
}
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();