👟 [React源码解析] 15. 手写Hooks

javascriptCopy
import React from "react";
import ReactDOM from "react-dom";
let isMount = true;
let workInProgressHook;
const fiber = {
memoizedState: null, // hook链表
stateNode: App, // dom
};
function mountWorkInProgressHook() {
const hook = {
memoizedState: null,
quene: {
pending: null, // 未执行的update
},
next: null, // 下一个hook
};
if (!fiber.memoizedState) {
fiber.memoizedState = hook;
} else {
// 上一个链表加上hook
workInProgressHook.next = hook;
}
workInProgressHook = hook;
return workInProgressHook;
}
function updateWorkInProgressHook() {
let currentGook = workInProgressHook;
workInProgressHook = workInProgressHook.next;
return currentGook;
}
function useState(initialState) {
let hook;
if (isMount) {
hook = mountWorkInProgressHook();
hook.memoizedState = initialState;
} else {
hook = updateWorkInProgressHook();
}
let baseState = hook.memoizedState;
if (hook.quene.pending) {
let fristUpdate = hook.quene.pending.next;
do {
const action = fristUpdate.action;
baseState = action(baseState);
fristUpdate = fristUpdate.next;
} while (fristUpdate !== hook.quene.pending);
hook.quene.pending = null;
}
hook.memoizedState = baseState;
return [baseState, dispacthAction.bind(null, hook.quene)];
}
function dispacthAction(quene, action) {
const update = {
action,
next: null,
};
if (quene.pending === null) {
update.next = update;
} else {
update.next = quene.pending.next;
quene.pending.next = update;
}
quene.pending = update;
isMount = false;
workInProgressHook = fiber.memoizedState;
schudule();
}
const Dispatcher = {
useState,
};
function App() {
const [age, addAge] = Dispatcher.useState(10);
const [count, addcount] = Dispatcher.useState(0);
return (
<>
<p>{age}</p>
<button onClick={() => addAge((age) => age + 1)}> add age </button>
<p>{count}</p>
<button onClick={() => addcount((count) => count + 1)}> add count </button>
</>
);
}
function schudule() {
ReactDOM.render(<App></App>, document.getElementById("root"));
}
schudule();