美文网首页
模拟实现hook useState

模拟实现hook useState

作者: _嘿嘿_ | 来源:发表于2021-07-30 18:31 被阅读0次
    //是否是第一次加载
    let isMount = true;
    //fiber 链表指针
    let workInProgressHook = null;
    
    //每个组件对应一个fiber对象
    let fiber = {
        //保存组件函数
        stateNode:App,
        //保存组件对应的hooks 数据链表
        memoizedState:null
    
    }
    
    function useState(initialState){
        //生成一个hook 对象
        let hook;
        if(isMount){
           //第一次加载初始化hook对象
           hook = {
             memoizedState:initialState,
             next:null,
             queue:{
                pending:null
             }   
           }
           //当是第一个useState的时候     
           if(!fiber.memoizedState){
               fiber.memoizedState = hook;
           }else{
               //挂在到最后一个
                workInProgressHook.next = hook;
           }
           //移动指针到最后一个
           workInProgressHook = hook;
        }else{
            //更新,非第一次加载
            //设置当前hook对象
            hook = workInProgressHook;
            //指针后移
            workInProgressHook = hook.next;
        }
        //获取hook对应的值
        let baseState = hook.memoizedState;
    
        //需要更新,环状链表遍历
        if(hook.queue.pending){
            // 获取update环状单向链表中第一个update
            let firstUpdate = hook.queue.pending.next;
            do {
                // 执行update action
                const action = firstUpdate.action;
                baseState = action(baseState);
                firstUpdate = firstUpdate.next;
                // 最后一个update执行完后跳出循环
              } while (firstUpdate !== hook.queue.pending.next);
        }
        //重新给hook 赋值
        hook.memoizedState = baseState;
        return [baseState,dispatchAction.bind(null,hook.queue)]
    
    }
    
    //memoizedState更新方法
    function dispatchAction(queue,action){
        //创建要更新的链表(环状)
         const update = {
             action:action,
             next:null
         }
         //与当前hook的操作对象queue关联
         //当前hook没有更新
         if(!queue.pending){
             //u0 -> u0
             update.next = update;
         }else{
             //u1 -> u0 ->u1
             update.next = queue.pending.next;
             queue.pending.next = update;
         }
         queue.pending = update;
        //模拟调度
        schedule();
    }
    
    
    
    //初始化调度render函数
    function schedule(){
        //指针指到第一个节点
        workInProgressHook = fiber.memoizedState;
        isMount = false;
        //触发组件render
        fiber.stateNode();
    }
    
    
    
    
    
    
    function App(){
        const [num,updateNum] = useState(0);
        const [num1,updateNum1] = useState(1);
        console.log(num,num1);
        return {
            click:()=>{
                updateNum(num=>num+1);
            }
        }
        
    }
    var test = App();
    test.click();
    
    

    相关文章

      网友评论

          本文标题:模拟实现hook useState

          本文链接:https://www.haomeiwen.com/subject/rjecvltx.html