手写实现一个useState函数

377 阅读1分钟

手写实现一个useState函数,主要考察链表在react中的应用

TeX\TeX
let isMount = true; // 申明一个全局变量,用来区分 mount 和 update
let workInProgressHook = null;
// 节点
const fiber = {
    stateNode: App, // stateNode 用来保存当前组件
    memoizedState: null,  // 用来保存当前组件内部的状态
}
function schedule() {
    // 每次运行时将当前fiber指向workProgressHook
    workInProgressHook = fiber.memoizedState;
    // 触发组件render
    const app = fiber.stateNode();
    isMount = false;
    return app;
}
function useState(initState) {
   ...
}
function App() {
    const [num, setNum] = useState(0);
    return {
        onClick() {
            setNum(n => n + 1);
        },
    };
};

schedule().onClick()

完整版代码

let isMount = true; // 申明一个全局变量,用来区分 mount 和 update
let workInProgressHook = null; // 申明一个全局变量,作为链表的指针

const fiber = {
    stateNode: App, // stateNode 用来保存当前组件
    memoizedState: null, // 用来保存当前组件内部的状态
};

function useState(initialState) {
    let hook;
    if (isMount) {
        hook = {
            memoizedState: initialState,
            next: null,
            queue: {
                pending: null,
            }
        };
        if (!fiber.memoizedState) {
            fiber.memoizedState = hook;
        } else {
            workInProgressHook.next = hook;
        }
        workInProgressHook = hook;
    } else {
        hook = workInProgressHook;
        workInProgressHook = workInProgressHook.next;
    }
    let baseState = hook.memoizedState;
    if (hook.queue.pending) {
        let firstUpdate = hook.queue.pending.next;
        do {
            const action = firstUpdate.action;
            baseState = action(baseState);
            firstUpdate = firstUpdate.next;
        } while (firstUpdate !== hook.queue.pending.next);
        hook.queue.pending = null; // 循环结束,清空链表
    }
    hook.memoizedState = baseState;
    return [baseState, dispatchAction.bind(null, hook.queue)];
};

function dispatchAction(queue, action) {
    const update = {
        action,
        next: null,
    };
    if (queue.pending === null) {
        update.next = update;
    } else {
        update.next = queue.pending.next;
        queue.pending.next = update;
    }
    queue.pending = update;
    schedule();
};

function schedule() {
    workInProgressHook = fiber.memoizedState; // 让指针指向当前的useState保存的值
    const app = fiber.stateNode(); // 执行组件的渲染函数,将结果保存在app里
    isMount = false; // 首次渲染之后,isMount 变成 false
    return app; // 将fiber.stateNode的结果返回
};

function App() {
    const [num, setNum] = useState(0);
    console.log(num);
    return {
        onClick() {
            setNum(n => n + 1);
        },
    };
};