zoukankan      html  css  js  c++  java
  • react 16 Hooks渲染流程

    useState

    react对useState进行了封装,调用了mountState。

    function useState<S>(
        initialState: (() => S) | S,
    ): [S, Dispatch<BasicStateAction<S>>] {
        currentHookNameInDev = 'useState';
        mountHookTypesDev();
        const prevDispatcher = ReactCurrentDispatcher.current;
        ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;
        try {
            return mountState(initialState);
        } finally {
            ReactCurrentDispatcher.current = prevDispatcher;
        }
    }
    

    mountState

    如果initialState是函数还可以执行。
    生成一个dispatch方法,通过闭包绑定当前states。
    把初始值存到memoizedState上。这个memoizedState绑定到fiber树上。用来存储state。

    function mountState<S>(
      initialState: (() => S) | S,
    ): [S, Dispatch<BasicStateAction<S>>] {
        // 把hooks加入queue,实际上是为了保证执行顺序。
      const hook = mountWorkInProgressHook();
      if (typeof initialState === 'function') {
        initialState = initialState();
      }
      hook.memoizedState = hook.baseState = initialState;
      const queue = (hook.queue = {
        last: null,
        dispatch: null,
        lastRenderedReducer: basicStateReducer,
        lastRenderedState: (initialState: any),
      });
      const dispatch: Dispatch<
        BasicStateAction<S>,
      > = (queue.dispatch = (dispatchAction.bind(
        null,
        // Flow doesn't know this is non-null, but we do.
        ((currentlyRenderingFiber: any): Fiber),
        queue,
      ): any));
      return [hook.memoizedState, dispatch];
    }
    

    memoizedState

    react其实不知道我们调用了几次useState。
    所以还是在memoizedState上动手脚,这个处理体现在mountWorkInProgressHook

     memoizedState: {
      baseState,
      next,
      baseUpdate,
      queue,
      memoizedState
    }
    

    memoizedState.next就是下一次useState的hook对象。

    hook1 === Fiber.memoizedState
    state1 === hook1.memoizedState
    state2 = hook1.next.memoizedState
    

    因为以这种方式存储,所以usestate必须在functionalComponent的根作用域中。不能被for,和if。

    setstate

    mountState函数返回的是 return [hook.memoizedState, dispatch];
    dispatch通过闭包就可以处理state。

    更新

    useState在更新的时候是调用的updateState,这个函数其实是封装的updateReducer。

    function renderWithHooks(){
        ReactCurrentDispatcher.current =
          nextCurrentHook === null
            ? HooksDispatcherOnMount
            : HooksDispatcherOnUpdate;
    };
    HooksDispatcherOnMount: {
        useState: mountState,
    }
    HooksDispatcherOnUpdate: {
        useState: updateState,
    }
    

    updateReducer

    可以看到updateReducer把新的fiber中的state值更新,返回新的值。然后后续走渲染流程。(之前写过reat 的渲染流程)
    还可以看到这有个循环update = update.next; while (update !== null && update !== first);
    这就是hooks的batchUpdate。

    function updateReducer<S, I, A>(
      reducer: (S, A) => S,
      initialArg: I,
      init?: I => S,
    ): [S, Dispatch<A>] {
      const hook = updateWorkInProgressHook();
      const queue = hook.queue;
    
      queue.lastRenderedReducer = reducer;
    
      // ...
      // The last update in the entire queue
      const last = queue.last;
      // The last update that is part of the base state.
      const baseUpdate = hook.baseUpdate;
      const baseState = hook.baseState;
    
      // Find the first unprocessed update.
      let first;
      if (baseUpdate !== null) {
        if (last !== null) {
          // For the first update, the queue is a circular linked list where
          // `queue.last.next = queue.first`. Once the first update commits, and
          // the `baseUpdate` is no longer empty, we can unravel the list.
          last.next = null;
        }
        first = baseUpdate.next;
      } else {
        first = last !== null ? last.next : null;
      }
      if (first !== null) {
        let newState = baseState;
        let newBaseState = null;
        let newBaseUpdate = null;
        let prevUpdate = baseUpdate;
        let update = first;
        let didSkip = false;
        do {
          const updateExpirationTime = update.expirationTime;
          if (updateExpirationTime < renderExpirationTime) {
            // Priority is insufficient. Skip this update. If this is the first
            // skipped update, the previous update/state is the new base
            // update/state.
            if (!didSkip) {
              didSkip = true;
              newBaseUpdate = prevUpdate;
              newBaseState = newState;
            }
            // Update the remaining priority in the queue.
            if (updateExpirationTime > remainingExpirationTime) {
              remainingExpirationTime = updateExpirationTime;
            }
          } else {
            markRenderEventTimeAndConfig(
              updateExpirationTime,
              update.suspenseConfig,
            );
    
            // Process this update.
            if (update.eagerReducer === reducer) {
              // If this update was processed eagerly, and its reducer matches the
              // current reducer, we can use the eagerly computed state.
              newState = ((update.eagerState: any): S);
            } else {
              const action = update.action;
              newState = reducer(newState, action);
            }
          }
          prevUpdate = update;
          update = update.next;
        } while (update !== null && update !== first);
    
        if (!didSkip) {
          newBaseUpdate = prevUpdate;
          newBaseState = newState;
        }
    
        // Mark that the fiber performed work, but only if the new state is
        // different from the current state.
        if (!is(newState, hook.memoizedState)) {
          markWorkInProgressReceivedUpdate();
        }
    
        hook.memoizedState = newState;
        hook.baseUpdate = newBaseUpdate;
        hook.baseState = newBaseState;
    
        queue.lastRenderedState = newState;
      }
    
      const dispatch: Dispatch<A> = (queue.dispatch: any);
      return [hook.memoizedState, dispatch];
    }
    
  • 相关阅读:
    20145222黄亚奇《网络对抗》MSF基础应用
    20145222黄亚奇《网络对抗》 逆向及BOF进阶实践学习总结
    20145222《网络对抗》 免杀原理与实践
    20145222黄亚奇《网络对抗》- shellcode注入&Return-to-libc攻击深入
    网络攻防20145222黄亚奇 《网络攻防》免杀原理与实践
    20145222 黄亚奇 《网络攻防》 后门原理与实践
    第十六周课程总结
    20145104张家明实验五
    20145104张家明 《Java程序设计》第10周学习总结
    20145104张家明 《Java程序设计》第四次实验设计
  • 原文地址:https://www.cnblogs.com/dh-dh/p/11278022.html
Copyright © 2011-2022 走看看