React19源码系列之 API (react)

本次文件记录react库中相关API函数的使用及起源码实现。

createRef:createRef – React

createContext:createContext – React 中文文档

memo:memo – React 中文文档

startTransition:startTransition – React 中文文档

use:use – React 中文文档

lazy:lazy – React

createRef

React 中 createRef 函数的实现,主要用于 创建一个可变的 ref 对象,该对象在组件的整个生命周期内保持不变。createRef 主要用于 class 组件

 function createRef(): RefObject {
  const refObject = {
    current: null,
  };
  return refObject;
}

createContext

React 中 createContext 函数的实现,主要用于 创建上下文(Context)对象,实现跨组件层级的数据共享。

function createContext<T>(defaultValue: T): ReactContext<T> {

  // 创建上下文对象
  const context: ReactContext<T> = {
    $$typeof: REACT_CONTEXT_TYPE,// 标记对象类型,用于 React 内部识别。
    _currentValue: defaultValue,// 存储不同渲染阶段的上下文值
    _currentValue2: defaultValue,// 存储不同渲染阶段的上下文值
    _threadCount: 0,// 并发线程计数(用于并发模式下的状态追踪)。
    // These are circular
    Provider: (null: any),// 提供上下文的组件
    Consumer: (null: any),// 消费上下文的组件
  };

  if (enableRenderableContext) {
    // 新 API 模式(函数式)
    context.Provider = context;
    context.Consumer = {
      $$typeof: REACT_CONSUMER_TYPE,
      _context: context,
    };
    
  } else {
     // 旧 API 模式(render prop)
    (context: any).Provider = {
      $$typeof: REACT_PROVIDER_TYPE,
      _context: context,
    };

    (context: any).Consumer = context;
    
  }
  return context;
}

memo

memo 函数是 React 中用于创建记忆化组件的高阶函数,它的作用是对传入的组件进行包装,返回一个新的组件类型。这个新组件会对前后两次的 props 进行比较,如果 props 没有发生变化,React 就不会重新渲染该组件,从而避免不必要的渲染,提高性能。

function memo<Props>(
  type: React$ElementType,
  compare?: (oldProps: Props, newProps: Props) => boolean,
) {
   // 创建新的元素类型对象
  const elementType = {
    $$typeof: REACT_MEMO_TYPE,
    type,
    compare: compare === undefined ? null : compare,
  };

  return elementType;
}

startTransition

React 中 过渡(Transition)机制 的核心实现,主要用于 将高优先级的紧急更新转换为低优先级的过渡更新

function startTransition(
  scope: () => void,
  options?: StartTransitionOptions,
) {
  // ReactSharedInternals.T 存储当前过渡上下文。
  const prevTransition = ReactSharedInternals.T;
  const currentTransition: BatchConfigTransition = {};
  ReactSharedInternals.T = currentTransition;

//  支持过渡命名
  if (enableTransitionTracing) {
    if (options !== undefined && options.name !== undefined) {
      currentTransition.name = options.name;
      currentTransition.startTime = -1;
    }
  }

  // 执行过渡回调(异步模式)
  if (enableAsyncActions) {
    try {
      // 执行用户传入的回调,其中的 setState 会被标记为过渡更新。
      const returnValue = scope();
      
      const onStartTransitionFinish = ReactSharedInternals.S;
      
      if (onStartTransitionFinish !== null) {
        onStartTransitionFinish(currentTransition, returnValue);
      }

      // 处理异步返回值(Promise)
      if (
        typeof returnValue === 'object' &&
        returnValue !== null &&
        typeof returnValue.then === 'function'
      ) {
        returnValue.then(noop, reportGlobalError);
      }
      
    } catch (error) {
      // 捕获同步错误
      reportGlobalError(error);
      
    } finally {
      // 检查过渡期间是否存在未完成的订阅(如 useEffect 未清理),并发出警告。
      // warnAboutTransitionSubscriptions(prevTransition, currentTransition);
      // 恢复旧上下文
      ReactSharedInternals.T = prevTransition;
    }
    
  } else {
    try {
      scope();
    } finally {
      // warnAboutTransitionSubscriptions(prevTransition, currentTransition);
      ReactSharedInternals.T = prevTransition;
    }
  }
}
type StartTransitionOptions = {
  name?: string,
};

type BatchConfigTransition = {
  name?: string,
  startTime?: number,
  _updatedFibers?: Set<Fiber>,
};

ReactSharedInternals.S

React 中 异步过渡(Async Transition) 机制的核心实现,主要用于 处理过渡回调返回的 Promise,并将其与过渡生命周期绑定

ReactSharedInternals.S = function onStartTransitionFinishForReconciler(
  transition: BatchConfigTransition,
  returnValue: mixed,
) {
  if (
    enableAsyncActions &&
    typeof returnValue === 'object' &&
    returnValue !== null &&
    typeof returnValue.then === 'function'
  ) {
    // 启动计时器,记录过渡开始时间。
    startAsyncTransitionTimer();

    const thenable: Thenable<mixed> = (returnValue: any);
    // 将过渡与 Promise 绑定,确保 Promise 状态变化能触发相应的过渡回调。
    entangleAsyncAction(transition, thenable);
  }
  // 链式调用前一个回调
  if (prevOnStartTransitionFinish !== null) {
    prevOnStartTransitionFinish(transition, returnValue);
  }
};

entangleAsyncAction

React 中 异步过渡(Async Transition) 机制的核心实现,主要用于 将异步操作(如 Promise)与过渡生命周期绑定,确保异步操作的完成状态能正确影响 UI 更新。

function entangleAsyncAction<S>(
  transition: BatchConfigTransition,
  thenable: Thenable<S>,
): Thenable<S> {
  // 1.初始化异步操作上下文
  
  // currentEntangledListeners:存储所有异步操作完成后的回调函数。
  if (currentEntangledListeners === null) {
    // There's no outer async action scope. Create a new one.
    const entangledListeners = (currentEntangledListeners = []);
    
    // 记录未完成的异步操作数量。
    currentEntangledPendingCount = 0;

    // 获取过渡车道(Lane),用于优先级调度。
    currentEntangledLane = requestTransitionLane(transition);

    // entangledThenable:自定义 Promise 接口,用于收集所有异步操作的完成回调。
    const entangledThenable: Thenable<void> = {
      status: 'pending',
      value: undefined,
      then(resolve: void => mixed) {
        entangledListeners.push(resolve);
      },
    };
    currentEntangledActionThenable = entangledThenable;
  }
  // 2.增加未完成计数并绑定回调
  // 未完成异步操作数量加 1。
  currentEntangledPendingCount++;
  // 无论 Promise 成功或失败,都调用 pingEngtangledActionScope。
  thenable.then(pingEngtangledActionScope, pingEngtangledActionScope);

  return thenable;
}

pingEngtangledActionScope

React 中 异步过渡(Async Transition) 机制的核心回调函数,主要用于 在所有关联的异步操作完成后触发 UI 更新

function pingEngtangledActionScope() {
  // 当计数减为 0 时,表示所有异步操作已完成。
  if (--currentEntangledPendingCount === 0) {
    // if (enableProfilerTimer && enableComponentPerformanceTrack) {
    //   if (!hasScheduledTransitionWork()) {
    //    // 停止性能计时器(如果启用了性能追踪)。
    //     clearAsyncTransitionTimer();
    //   }
    // }
    if (currentEntangledListeners !== null) {
      // All the actions have finished. Close the entangled async action scope
      // and notify all the listeners.
      if (currentEntangledActionThenable !== null) {
        const fulfilledThenable: FulfilledThenable<void> = (currentEntangledActionThenable: any);
        // 将其状态标记为 'fulfilled',表示所有操作已完成。
        fulfilledThenable.status = 'fulfilled';
      }
      const listeners = currentEntangledListeners;
      // 清空 currentEntangledListeners
      currentEntangledListeners = null;
      // 重置 currentEntangledLane(过渡优先级车道)
      currentEntangledLane = NoLane;
      currentEntangledActionThenable = null;

      // 执行所有注册的回调函数(listeners),触发 React 的渲染流程。
      for (let i = 0; i < listeners.length; i++) {
        const listener = listeners[i];
        listener();
      }
    }
  }
}

let currentEntangledListeners: Array<() => mixed> | null = null;

use

lazy

lazy 函数用于创建懒加载组件。懒加载组件允许开发者在需要时才加载组件代码,而不是在应用启动时就加载所有组件代码,从而提高应用的加载性能。代码通过定义不同的加载状态常量,并使用一个闭包来管理组件的加载过程,实现了组件的懒加载功能。

函数参数说明:

  • 参数 ctor:类型为 () => Thenable<{default: T, ...}>,是一个返回 Promise 的函数。这个函数通常是动态导入组件的函数,例如 () => import('./MyComponent')
function lazy<T>(
  ctor: () => Thenable<{default: T, ...}>,
): LazyComponent<T, Payload<T>> {

  // 创建负载对象 payload
  const payload: Payload<T> = {
    //初始状态为 Uninitialized,表示组件还未开始加载。
    _status: Uninitialized,
    // 存储 ctor 函数,即动态导入组件的函数。
    _result: ctor,
  };

// 创建懒加载组件对象 lazyType
  const lazyType: LazyComponent<T, Payload<T>> = {
    // 值为 REACT_LAZY_TYPE,这是 React 用于标识懒加载组件的特殊属性。
    $$typeof: REACT_LAZY_TYPE,
    // 存储前面创建的 payload 对象,包含组件的加载状态和动态导入函数。
    _payload: payload,
    // 指向 lazyInitializer 函数,该函数用于初始化组件的加载过程。
    _init: lazyInitializer,
  };

  // 返回懒加载组件对象
  return lazyType;
}
type LazyComponent<T, P> = {
  $$typeof: symbol | number,
  _payload: P,
  _init: (payload: P) => T,
  _debugInfo?: null | ReactDebugInfo,
};

 Promise 或异步操作的不同状态

  • Uninitialized:值为 -1,表示组件还未开始加载,处于未初始化状态。
  • Pending:值为 0,表示组件正在加载中。
  • Resolved:值为 1,表示组件已经成功加载。
  • Rejected:值为 2,表示组件加载失败。
const Uninitialized = -1;
const Pending = 0;
const Resolved = 1;
const Rejected = 2;

lazyInitializer

lazyInitializer 函数是 React 中用于实现懒加载组件初始化逻辑的核心函数。它负责处理懒加载组件的加载过程,根据组件的不同加载状态(未初始化、加载中、已加载、加载失败)执行相应的操作,最终返回加载好的组件或者抛出加载错误。

function lazyInitializer<T>(payload: Payload<T>): T {
  if (payload._status === Uninitialized) {// Uninitialized代表-1

    // 从 payload._result 中获取动态导入组件的函数 ctor 并执行,得到一个 Promise 对象 thenable。
    const ctor = payload._result;
    const thenable = ctor();

    // 处理 Promise 的结果
    thenable.then(
      // 当 thenable 成功解决时,检查 payload 的状态是否为 Pending(加载中)或 Uninitialized(未初始化)。如果是,则将 payload 的状态更新为 Resolved(已加载),并将加载的模块对象存储在 _result 中。
      moduleObject => {
        if (
          (payload: Payload<T>)._status === Pending ||
          payload._status === Uninitialized
        ) {
          // Transition to the next state.
          const resolved: ResolvedPayload<T> = (payload: any);
          //代表组件加载完成
          resolved._status = Resolved;
          //执行结果
          resolved._result = moduleObject;
        }
      },
      // 当 thenable 被拒绝时,同样检查 payload 的状态。如果是 Pending 或 Uninitialized,则将 payload 的状态更新为 Rejected(加载失败),并将错误信息存储在 _result 中。
      error => {
        if ( //Pending代表0
          (payload: Payload<T>)._status === Pending ||
          payload._status === Uninitialized
        ) {
          // Transition to the next state.
          const rejected: RejectedPayload = (payload: any);
          // 组件加载失败
          rejected._status = Rejected;//Rejected代表2 
          rejected._result = error;
        }
      },
    );
    
    //如果在处理 Promise 后,payload 的状态仍然是 Uninitialized,则将其状态更新为 Pending(加载中),并将 thenable 存储在 _result 中。
    if (payload._status === Uninitialized) {
      const pending: PendingPayload = (payload: any);
      pending._status = Pending;
      pending._result = thenable;
    }
  }
  
  // 返回加载结果
  // 如果 payload._status 为 Resolved(已加载),则从 payload._result 中获取加载的模块对象,并返回其 default 属性,通常这就是懒加载的组件。
  if (payload._status === Resolved) {//Resolved代表1
    const moduleObject = payload._result;
    return moduleObject.default;
  } else {
    // 抛出错误
    throw payload._result;
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值