极简hook实现

362 阅读1分钟
    // 当前正在执行的hook
    let workInprogressHook = null;
    // 模拟是否已经挂载了
    let isMount = true;
    // fiber容器
    const fiber = {
        memoizedState: null,
        stateNode: App
    }
    function run() {
        workInprogressHook = fiber.memoizedState;
        const app = fiber.stateNode();
        isMount = false;
        return app;
    }
    // dispatch
    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;
        run();
    }
    // 设置setState
    function setState(initalState) {
        let hook = null;
        // 未挂载
        if(isMount) {
            hook = {
                queue: {
                    pending:null,
                },
                memoizedState: initalState,
                next: null,
            }
            if(fiber.memoizedState === null) {
                fiber.memoizedState = hook;
            } else {
                workInprogressHook.next = hook;
            }
            workInprogressHook = hook;
        } else {
            hook = workInprogressHook;
            workInprogressHook = workInprogressHook.next;
        }

        let baseState = hook.memoizedState;
        if(hook.queue.pending) {
            let update = hook.queue.pending.next;
            do{
                const action = update.action;
                baseState = action(baseState);
                update = update.next;
            } while(update !== hook.queue.pending.next)
        }

        return [baseState, dispatchAction.bind(null, hook.queue)]

    }


    function App() {
        const [count, setCount] = setState(0);
        console.log(`count is ${count}`);
        // 未返回jsx对象,只是返回了模拟对象
        return {
            onClick: () => {
                setCount(num => num + 1);
            }
        }
    }

    window.app = run()