美文网首页
react hooks 源码解读

react hooks 源码解读

作者: 芗芗_ | 来源:发表于2021-03-21 02:17 被阅读0次

    ReactFiberWorkLoop.new.js
    performUnitOfWork()调用了beginWork()返回一个workInProgress

    workInProgress是一个Fiber类型,一个Fiber就是一个任务,是分片调度的最小单位

    ReactFiberBeginWork.new.js
    function beginWork(
      current: Fiber | null,
      workInProgress: Fiber,
      renderLanes: Lanes,
    ){
    return updateFunctionComponent(
            current,
            workInProgress,
            Component,
            resolvedProps,
            renderLanes,
          )
    }
    // beginWork方法候根据的传入的workInProgress.tag判断当前组件的tag,
    // 根据tag来确认调用的update函数, tag == FunctionComponent
    // 返回updateFunctionComponent()
    
    function updateFunctionComponent(
      current,
      workInProgress,
      Component,
      nextProps: any,
      renderLanes,
    ){
    nextChildren = renderWithHooks(
          current,
          workInProgress,
          Component,
          nextProps,
          context,
          renderLanes,
        );
     reconcileChildren(current, workInProgress, nextChildren, renderLanes);
      return workInProgress.child;
    }
    // updateFunctionComponent通过调用renderWithHooks()得到nextChildren
    // 调用reconcileChildren(current, workInProgress, nextChildren, renderLanes);
    // 返回workInProgress.child
    
    
    ReactFiberHooks.new.js
    function renderWithHooks<Props, SecondArg>(
      current: Fiber | null,
      workInProgress: Fiber,
      Component: (p: Props, arg: SecondArg) => any,
      props: Props,
      secondArg: SecondArg,
      nextRenderLanes: Lanes,
    ) {
     ReactCurrentDispatcher.current =
          current === null || current.memoizedState === null
            ? HooksDispatcherOnMount
            : HooksDispatcherOnUpdate;
     let children = Component(props, secondArg);
    
    return children;
    }
    // renderWithHooks中ReactCurrentDispatcher.current会根据memoizedState
    // 是否初始化来赋值HooksDispatcherOnMount或者是HooksDispatcherOnUpdate
    // 首次调用useState时候ReactCurrentDispatcher.current被赋值为HooksDispatcherOnMount
    // HooksDispatcherOnMount对象的useState指向mountState
    
    function mountState<S>(
      initialState: (() => S) | S,
    ){
     const hook = mountWorkInProgressHook();
     hook.memoizedState = hook.baseState = initialState;
      const queue = (hook.queue = {
        pending: null,
        interleaved: null,
        lanes: NoLanes,
        dispatch: null,
        lastRenderedReducer: basicStateReducer,
        lastRenderedState: (initialState: any),
      });
      const dispatch: Dispatch<
        BasicStateAction<S>,
      > = (queue.dispatch = (dispatchAction.bind(
        null,
        currentlyRenderingFiber,
        queue,
      ): any));
      return [hook.memoizedState, dispatch];
    }
    // mountState首先用mountWorkInProgressHook创建一个hook
    // 且创建一个workInProgressHook链表,把当前的hook加入链表末端
    // 赋值 hook.memoizedState = hook.baseState = initialState;
    // 绑定dispatchAction函数 return [initialState,dispatchAction]
    const hook: Hook = {
      memoizedState: null,
      baseState: null,
      baseQueue: Update<S, A> || null,
      queue: UpdateQueue<S, A> || null, // UpdateQueue 更新队列
      next: null, // 列表的下一个hook
    };
    
    function dispatchAction<S, A>(
      fiber: Fiber,
      queue: UpdateQueue<S, A>,
      action: A,
    ) {
    const update: Update<S, A> = {
        lane,
        action,
        eagerReducer: null,
        eagerState: null, // // 待更新状态值
        next: (null: any),
      }; 
    const pending = queue.pending;
    if (pending === null) {
      // This is the first update. Create a circular list.
      update.next = update;
    } else {
      update.next = pending.next;
      pending.next = update;
    }
    queue.pending = update;    
    }
     const root = scheduleUpdateOnFiber(fiber, lane, eventTime);
    }
    // 再次调用useState的时候其实是在调用dispatchAction,
    // 利用闭包函数的特性,拿到hook.queue和hook.dispatch每次调用都在都在初始化创建hook.queue环状链表中加一个update对象
    // hook.queue.pending 永远指向最新创建的的update
    // 最后scheduleWork触发React的更新调度
    // 这个时候state值并没有改变,而是被缓存了起来,在下一次render时,函数组件里的useState又一次被调用,这个时候才是真的更新state
    

    再次render的时候ReactCurrentDispatcher.current
    === HooksDispatcherOnUpdate
    useState再次被调用触发HooksDispatcherOnUpdate.updateState

    ReactFiberHooks.new.js
    function updateState<S>(
      initialState: (() => S) | S,
    ): [S, Dispatch<BasicStateAction<S>>] {
      return updateReducer(basicStateReducer, (initialState: any));
    }
    
    function basicStateReducer<S>(state: S, action: BasicStateAction<S>): S {
      // $FlowFixMe: Flow doesn't like mixed types
      return typeof action === 'function' ? action(state) : action;
    }
    // updateState 返回updateReducer
    
    function updateReducer<S, I, A>(
      reducer: (S, A) => S,
      initialArg: I,
      init?: I => S,
    ): [S, Dispatch<A>] 
    {
     const hook = updateWorkInProgressHook(); // 取出当前的hook
      const queue = hook.queue; // 取出更新列表
    }
    
    
    

    相关文章

      网友评论

          本文标题:react hooks 源码解读

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