1. 首页
  2. React

React18 中的数据结构

JSX.Element

定义

JSX.Element 是一个 ReactElement,其 props 和 type 的泛型被设置为 any。之所以存在 JSX.Element 是因为不同的库实现 JSX 的方式不同,也就是说 JSX 是一个全局的命名空间,通过不同的库来设置,React 的设置如下:

declare namespace JSX {
    interface Element extends React.ReactElement<any, any> { }
}

在这里,JSX.Element 实际上是一个接口,它扩展了 React.ReactElementReact.ReactElement 是 React 中一个更具体的类型,用于描述一个 React 元素。ReactElement 本身是一个泛型接口,通常定义如下:

interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
    type: T;
    props: P;
    key: Key | null;
}

这意味着 JSX.Element 是一个具有 typepropskey 属性的对象,这些属性用来描述一个 React 元素的基本结构。

JSX.Element 是由 JSX 语法所生成的对象的类型。它是 React 元素的类型表示,描述了你在 React 应用中构建的用户界面。

当你编写 JSX 语法时,编译器(如Babel)将这些语法转化为等效的React.createElement() 调用所返回的对象类型。例如,以下 JSX 代码:

const myElement = <div>Hello, World!</div>;

在编译后实际上会变为:

const myElement = React.createElement("div", null, "Hello, World!");

这里的 myElement 类型就是 JSX.Element

用途

  • 作为组件的返回值:在React组件中,当你直接返回一个JSX表达式(如 <div>...</div>),该组件的返回类型就是 JSX.Element

  • 作为函数参数:当某个函数接受一个React元素作为参数时,可以将其类型声明为 JSX.Element。例如,一个负责渲染特定元素的高阶组件(HOC)可能有这样的签名:

function withSomeEnhancement(WrappedComponent: React.ComponentType): (props: Props) => JSX.Element {
   ... 
}
  • 作为数组元素或对象属性:当需要存储或传递一系列React元素(如在数组中存储多个子组件,或在对象字面量中作为属性值)时,这些元素的类型应为 JSX.Element

  • 用于表示由JSX编译出的单个React元素,常用于组件返回值、函数参数和数据结构。

ReactElement

定义

ReactElement是一个用于描述UI组件的对象,是React应用中的核心概念之一。ReactElement通常由React.createElement()方法创建,也可以通过JSX语法创建。

ReactElement 是React组件树中的基础构建块,是一个JavaScript对象,表示一个具体的React组件实例及其相关的属性和子元素。它的结构通常如下:

  • type:描述元素的类型,可以是一个HTML标签(如'div''span')或者是一个React组件(函数组件或类组件)。

  • props:一个对象,包含传递给该元素的所有属性和子元素。props是不可变的,通常包括className, style, children等。

  • key:用于在元素的兄弟元素中唯一标识元素,常用于列表渲染,以帮助React识别哪些元素发生了变化。

  • ref:一个特殊属性,用于获取对DOM元素或类组件实例的引用。

export type Source = {|
  fileName: string,
  lineNumber: number,
|};

export type ReactElement = {|
  // React 元素的唯一标识
  // Symbol.for('react.element')
  $typeof: any,
  // 元素的内置属性
  // dom是标签名、函数组件是函数本身、类组件是类本身
  type: any,
  // for循环中的key,不加默认用index代替
  key: any,
  // 组件ref
  ref: any,
  // 组件的props
  props: any,
  // ReactFiber
  _owner: any,

  // __DEV__
  _store: {validated: boolean, ...},
  _self: React$Element<any>,
  _shadowChildren: any,
  _source: Source,
|};

用途

  • 组件渲染:每当使用JSX语法编写组件时,实际上是在创建ReactElement对象。React使用这些对象来构建虚拟DOM树,并最终渲染到实际DOM中。

  • 低级别操作:直接操作React组件树(如在自定义的shouldComponentUpdateReact.Children.map等方法中)时,可能会遇到 ReactElement 对象。

  • 类型细化:在需要确保变量或参数具体为React组件实例(而非其他ReactNode类型)时,可以使用 ReactElement 类型。
    尽管在大多数情况下,JSX.Element 已足够,但在某些涉及更底层React API或高级类型技巧的场景中,可能需要明确使用 ReactElement

  • 函数组件返回 ReactElement

  • 最底层的React组件实例表示,用于直接操作组件树或在需要精确类型控制时使用。在实际编码中,通常较少直接指定为 ReactElement 类型,更多使用 JSX.Element

ReactNode

定义

ReactNode 是一个更宽泛的类型,其本身不是一个对象,因此没有属性,但它包括了多种可能的类型组合。它包含了所有React认为合法的“节点”,不仅包括 JSX.Element,还包括以下几种类型:

  • JSX 元素:这是最常见的 ReactNode 类型,表示通过 JSX 语法创建的 React 元素,在这里可以认为是React$Element<any>

  • 字符串(string

  • 数字(number

  • 数组:一个数组可以包含其他 ReactNode 类型的元素。

  • 布尔值(boolean):布尔值本身不会被渲染,但可以用于条件渲染。true && <div>Will render if true</div>

  • nullundefined:这两者表示什么都不渲染。

  • ReactFragment(由数组或<>...</>语法创建的多个并列子元素)

  • ReactPortal(用于将子元素插入到DOM的其他位置,如ReactDOM.createPortal()返回的类型)

export type ReactNode =
  | React$Element<any>
  | ReactPortal
  | ReactText
  | ReactFragment
  | ReactProvider<any>
  | ReactConsumer<any>;

export type ReactEmpty = null | void | boolean;

export type ReactFragment = ReactEmpty | Iterable<React$Node>;

export type ReactNodeList = ReactEmpty | React$Node;

export type ReactText = string | number;

export type ReactProvider<T> = {
  $typeof: Symbol | number,
  type: ReactProviderType<T>,
  key: null | string,
  ref: null,
  props: {
    value: T,
    children?: ReactNodeList,
    ...
  },
  ...
};

export type ReactProviderType<T> = {
  $typeof: Symbol | number,
  _context: ReactContext<T>,
  ...
};

export type ReactConsumer<T> = {
  $typeof: Symbol | number,
  type: ReactContext<T>,
  key: null | string,
  ref: null,
  props: {
    children: (value: T) => ReactNodeList,
    unstable_observedBits?: number,
    ...
  },
  ...
};

export type ReactContext<T> = {
  $typeof: Symbol | number,
  Consumer: ReactContext<T>,
  Provider: ReactProviderType<T>,
  _calculateChangedBits: ((a: T, b: T) => number) | null,
  _currentValue: T,
  _currentValue2: T,
  _threadCount: number,
  // DEV only
  _currentRenderer?: Object | null,
  _currentRenderer2?: Object | null,
  // This value may be added by application code
  // to improve DEV tooling display names
  displayName?: string,
  ...
};

export type ReactPortal = {
  $typeof: Symbol | number,
  key: null | string,
  containerInfo: any,
  children: ReactNodeList,
  // TODO: figure out the API for cross-renderer implementation.
  implementation: any,
  ...
};

用途

  • 作为组件的children属性:当一个组件允许接收任意类型的子元素(不仅仅是单一的React元素)时,其 children 属性类型通常被声明为 ReactNode
    这样可以接收字符串、数字、布尔值、空值、React元素数组、Fragments等。

interface MyComponentProps {
  children: React.ReactNode;
}

const MyComponent: React.FC<MyComponentProps> = ({ children }) => {
  return <div>{children}</div>;
};
  • 泛型约束:在需要处理可能包含多种React节点类型的集合或结构时,可以使用 ReactNode 作为泛型约束,确保这些结构只包含React认可的节点类型。

  • 类组件的渲染方法返回 ReactNode

  • 涵盖所有React允许的节点类型,包括但不限于React元素、基本类型值、Fragments和Portals,常用于组件的children属性和需要处理多种节点类型的情况。

ReactFragment

定义

React.Fragment 本身没有属性,因为它的主要目的是作为一个容器来包裹子元素,而不对这些元素进行任何直接的修改或影响。唯一与 React.Fragment 相关的属性是 key,用于优化列表渲染。

key: 当使用数组来渲染多个 Fragment 时,可以通过 key 属性来提高渲染性能和帮助 React 识别每个子元素的变化。

export type ReactFragment = ReactEmpty | Iterable<React$Node>;

export type ReactEmpty = null | void | boolean;

用途

1.包裹多个子元素:
在 JSX 中,每个组件只能返回一个单一的顶级元素。使用 React.Fragment 可以在不增加额外的 DOM 层级的情况下返回多个元素。这里的 <> 和 </> 就是 <React.Fragment> 和 </React.Fragment>

function App() {
  return (
    <>
      <h1>Hello, World!</h1>
      <p>This is a paragraph.</p>
    </>
  );
}

2.列表渲染

当在列表中使用 React.Fragment 时,可以通过 key 属性来帮助 React 区分不同的片段。

function ItemList({ items }) {
  return (
    <>
      {items.map(item => (
        <React.Fragment key={item.id}>
          <h2>{item.title}</h2>
          <p>{item.description}</p>
        </React.Fragment>
      ))}
    </>
  );
}

3.避免不必要的 DOM 元素
使用 React.Fragment 可以避免在 DOM 中生成不必要的包裹元素,这在需要保持 HTML 结构简洁时非常有用。

ReactContext

定义

Provider:

  • Provider 是一个 React 组件,它允许使用这个 Context 的组件订阅 Context 的变化。

  • Provider 接收一个 value 属性,这个 value 会传递给树中所有使用这个 Context 的组件。无论多深,所有的消费者都会重新渲染,当 Providervalue 发生变化时。

  • 典型的用法是在组件树的顶层使用 Provider 来包裹需要共享状态的组件。

Consumer:

  • Consumer 是一个 React 组件,它允许你在函数组件中订阅 Context。

  • Consumer 需要一个函数作为子组件,这个函数接收当前的 Context 值并返回一个 React 节点。

  • Consumer 通常在较旧版本的 React 或者在类组件中使用。在函数组件中,使用 useContext 钩子会更简洁。

displayName:

  • displayName 是一个可选的字符串属性,主要用于调试。设置 displayName 可以帮助在 React 开发者工具中更容易地识别 Context。

export type ReactContext<T> = {
  $typeof: Symbol | number,
  Consumer: ReactContext<T>,
  Provider: ReactProviderType<T>,
  _calculateChangedBits: ((a: T, b: T) => number) | null,
  _currentValue: T,
  _currentValue2: T,
  _threadCount: number,
  // DEV only
  _currentRenderer?: Object | null,
  _currentRenderer2?: Object | null,
  // This value may be added by application code
  // to improve DEV tooling display names
  displayName?: string,
  ...
};

用途

  • 全局状态管理: Context 是一种轻量级的状态管理方案,适用于不太复杂的全局状态管理需求,比如主题切换、当前用户信息等。

  • 主题和样式: 通过 Context 可以在整个应用中传递主题信息,从而实现动态的样式切换。

  • 多语言支持 (i18n): 使用 Context 可以很方便地实现应用的国际化支持,通过在 Context 中存储当前语言和翻译函数。

  • 认证和用户信息: 可以通过 Context 将当前用户信息和认证状态在应用中共享。

  • 配置和环境变量: 在应用中共享一些配置数据或者环境变量。

在使用 Context 时,尤其是在大型应用中,要注意避免过度使用,因为频繁的 Context 更新可能会导致性能问题。对于复杂的状态管理需求,可能需要考虑使用更成熟的状态管理工具,比如 Redux 或者 MobX。

RefObject

定义

export type RefObject = {|
  current: any,
|};

current:

类型:T | null

说明:current 属性是 RefObject 的核心属性,它持有对组件或 DOM 元素的引用。在组件挂载时,current 会被设置为对应的 DOM 元素或组件实例;在组件卸载时,current 会被重置为 null

用途

1.访问 DOM 元素:通过 RefObject 可以直接访问到 DOM 元素,进而可以对其进行操作,例如获取焦点、修改样式或读取值。

import React, { useRef } from 'react';

function InputFocus() {
  const inputRef = useRef(null);

  const focusInput = () => {
    if (inputRef.current) {
      inputRef.current.focus();
    }
  };

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={focusInput}>Focus Input</button>
    </div>
  );
}

2.对于类组件,可以通过 RefObject 获取组件实例,从而调用实例方法或访问实例属性。

import React, { Component, createRef } from 'react';

class CustomComponent extends Component {
  doSomething() {
    console.log('Doing something');
  }

  render() {
    return <div>Custom Component</div>;
  }
}

class ParentComponent extends Component {
  constructor(props) {
    super(props);
    this.customComponentRef = createRef();
  }

  handleAction = () => {
    if (this.customComponentRef.current) {
      this.customComponentRef.current.doSomething();
    }
  };

  render() {
    return (
      <div>
        <CustomComponent ref={this.customComponentRef} />
        <button onClick={this.handleAction}>Call Method</button>
      </div>
    );
  }
}

3.保持状态不变的变量:useRef() 可以用于存储那些在组件生命周期内不需要重新渲染的变量。

function Timer() {
  const timerRef = useRef(0);

  const startTimer = () => {
    timerRef.current = setInterval(() => {
      console.log('Timer tick');
    }, 1000);
  };

  const stopTimer = () => {
    clearInterval(timerRef.current);
  };

  return (
    <div>
      <button onClick={startTimer}>Start Timer</button>
      <button onClick={stopTimer}>Stop Timer</button>
    </div>
  );
}

注意

  • RefObjectcurrent 属性是可变的,但更改它不会触发组件重新渲染。

  • 在函数组件中,useRef() 是一个非常强大的工具,特别是在需要获取最新的某个值但又不希望触发重新渲染的情况下。

  • 在严格模式下,React 会在挂载和卸载时调用 ref 回调两次,这可能会导致一些意想不到的行为,因此需要小心处理。

Fiber/FiberNode

定义

FiberNode 是用来创建 Fiber 对象的,是Fiber架构的核心。

workInProgress 就是 FiberNode。

export type Fiber = {|
  // These first fields are conceptually members of an Instance. This used to
  // be split into a separate type and intersected with the other Fiber fields,
  // but until Flow fixes its intersection bugs, we've merged them into a
  // single type.

  // An Instance is shared between all versions of a component. We can easily
  // break this out into a separate object to avoid copying so much to the
  // alternate versions of the tree. We put this on a single object for now to
  // minimize the number of objects created during the initial render.

  // Tag identifying the type of fiber.
  // 标记不同的组件类型
  // 作为静态属性,标识FunctionComponent/HostComponent/HostText等
  // 表示 Fiber 的类型,如函数组件、类组件、原生组件等。
  // 不同的 tag 值帮助 React 确定如何处理这个 Fiber 节点。
  tag: WorkTag,

  // Unique identifier of this child.
  // ReactElement 里面的 key 属性
  // 用于唯一标识 Fiber 的 key,这在列表渲染中尤为重要,以帮助 React 正确地更新和重用组件。
  key: null | string,

  // The value of element.type which is used to preserve the identity during
  // reconciliation of this child.
  // 类型:ReactElement.type
  // ReactElement.type,也就是我们调用 createElement() 的第一个参数
  // 大部分情况同type,某些情况不同,比如FunctionComponent使用React.memo包裹
  elementType: any,

  // The resolved function/class/ associated with this fiber.
  // 类型:function/class
  // 异步组件 resolved 之后返回的内容,一般是 function 或 class
  // 同ReactElement
  // 指向组件的实际类型(函数、类或字符串表示的 DOM 元素)。
  type: any,

  // The local state associated with this fiber.
  // 跟当前 Fiber 相关的本地状态
  // 类型:FiberRoot,DomElement,ReactComponentInstance
  // FiberNode会通过stateNode绑定一些其他的对象,例如FiberNode对应的Dom、FiberRoot、ReactComponent实例
  // 对于类组件,指向组件实例;对于 DOM 元素,指向对应的 DOM 节点。
  stateNode: any,

  // Conceptual aliases
  // parent : Instance -> return The parent happens to be the same as the
  // return fiber since we've merged the fiber and instance.

  // Remaining fields belong to Fiber

  // The Fiber to return to after finishing processing this one.
  // This is effectively the parent, but there can be multiple parents (two)
  // so this is only the parent of the thing we're currently processing.
  // It is conceptually the same as the return address of a stack frame.
  // 类型:FiberNode或null
  // 指向在 Fiber 节点树中的 parent,用来在处理完当前节点之后向上返回
  // 指向父 Fiber 节点,用于在树中向上遍历。
  return: Fiber | null,
  // 类型:FiberNode或null
  // Singly Linked List Tree Structure.
  // 单链表树结构
  // 指向第一个子 Fiber 节点,用于遍历子节点。
  child: Fiber | null,
  // 类型:FiberNode或null
  // 指向下一个兄弟 Fiber 节点,用于遍历同级节点。
  // 兄弟节点的 return 指向同一个 父节点
  sibling: Fiber | null,
  
  // 当前 Fiber 在同级兄弟节点中的位置索引。
  index: number,

  // The ref last used to attach this node.
  // I'll avoid adding an owner field for prod and model that as functions.
  // ReactElement的 ref 属性
  // 用于处理组件的 ref 属性,支持访问 DOM 元素或类组件实例。
  ref:
    | null
    | (((handle: mixed) => void) & {_stringRef: ?string, ...})
    | RefObject,

  // Input is the data coming into process this fiber. Arguments. Props.
  // This type will be more specific once we overload the tag.
  // 新的变动带来的新的 props
  // 作为工作单元,保存本次更新造成的状态改变相关信息
  // 要更新的新props
  // 表示新的props,来自element的props
  // 当前渲染周期正在使用的新属性。
  pendingProps: any, 
  // The props used to create the output.
  // 上一次渲染完成后的 props
  // 计算后的props
  // 表示上一次render时的props
  // 表示处理后的新state
  // 上一次渲染时的属性,用于比较新旧属性是否发生变化。
  memoizedProps: any, 

  // A queue of state updates and callbacks.
  // 该 Fiber 对应的组件产生的 Update 会存放在这个队列里
  // 更新队列,队列内放着即将要发生的变更状态
  // 存储挂起的状态更新和回调队列。
  updateQueue: mixed,

  // The state used to create the output
  // 上一次渲染的 state
  // 计算出的新状态
  // 当前 Fiber 节点的已处理状态。
  memoizedState: any,

  // Dependencies (contexts, events) for this fiber, if it has any
  // 一个列表,存放这个 Fiber 依赖的 context、event
  // 保存context、事件相关内容
  // 用于跟踪上下文依赖,以便在上下文变化时触发重新渲染。
  dependencies: Dependencies | null,

  // Bitfield that describes properties about the fiber and its subtree. E.g.
  // the ConcurrentMode flag indicates whether the subtree should be async-by-
  // default. When a fiber is created, it inherits the mode of its
  // parent. Additional flags can be set at creation time, but after that the
  // value should remain unchanged throughout the fiber's lifetime, particularly
  // before its child fibers are created.
  // 用来描述当前Fiber和他子树的`Bitfield`
  // 共存的模式表示这个子树是否默认是异步渲染的
  // Fiber被创建的时候他会继承父Fiber
  // 其他的标识也可以在创建的时候被设置
  // 但是在创建之后不应该再被修改,特别是他的子Fiber创建之前  
  // 用于标识 Fiber 树的模式(如并发模式)。                               
  mode: TypeOfMode,

  // Effect
  // 用来记录 Side Effect
  // 副作用
  // 用于标记需要在 Fiber 上执行的操作,如更新、删除等。React 18 中的 flags 替代了之前版本的 effectTag。
  flags: Flags,
  // 子树的所有节点的flags
  subtreeFlags: Flags,
  // 要删除的子fiberNode
  deletions: Array<Fiber> | null,

  // Singly linked list fast path to the next fiber with side-effects.
  // 单链表用来快速查找下一个 side effect 
  // 指向下一个需要处理副作用的 Fiber 节点。
  nextEffect: Fiber | null,

  // The first and last fiber with side-effect within this subtree. This allows
  // us to reuse a slice of the linked list when we reuse the work done within
  // this fiber.
  // 子树中的第一个 side effect 
  // 与副作用操作遍历流程相关 当前节点下,第一个需要处理的side effect
  firstEffect: Fiber | null,
  // 子树中的最后一个 side effect
  // 表示最后一个将要处理的side effect
  lastEffect: Fiber | null,

  // 用于调度 优先级
  // React 18 引入的概念,用于表示优先级队列,帮助调度更新。
  lanes: Lanes,
  childLanes: Lanes,

  // This is a pooled version of a Fiber. Every fiber that gets updated will
  // eventually have a pair. There are cases when we can clean up pairs to save
  // memory if we need to.
  // 连体婴儿  双缓存机制
  // 指向对应的workInProgress FiberNode或者current FiberNode
  // 类型:FiberNode或null
  // Fiber调度算法采取了双缓冲池算法,current的alternate指向workInProgerss ,
  // 指向旧的 Fiber,用于在新旧 Fiber 树之间进行对比。
  // 而workInProgress的alternate指向current,在创建workInProgerss的时候会尽量重用current.alternate
  alternate: Fiber | null,

  // 下面是调试相关的                                

  // Time spent rendering this Fiber and its descendants for the current update.
  // This tells us how well the tree makes use of sCU for memoization.
  // It is reset to 0 each time we render and only updated when we don't bailout.
  // This field is only set when the enableProfilerTimer flag is enabled.
  // 收集每个 Fiber 和 子树 渲染的时间                                   
  actualDuration?: number,

  // If the Fiber is currently active in the "render" phase,
  // This marks the time at which the work began.
  // This field is only set when the enableProfilerTimer flag is enabled.
  actualStartTime?: number,

  // Duration of the most recent render time for this Fiber.
  // This value is not updated when we bailout for memoization purposes.
  // This field is only set when the enableProfilerTimer flag is enabled.
  selfBaseDuration?: number,

  // Sum of base times for all descendants of this Fiber.
  // This value bubbles up during the "complete" phase.
  // This field is only set when the enableProfilerTimer flag is enabled.
  treeBaseDuration?: number,

  // Conceptual aliases
  // workInProgress : Fiber ->  alternate The alternate used for reuse happens
  // to be the same as work in progress.
  // __DEV__ only
  _debugID?: number,
  _debugSource?: Source | null,
  _debugOwner?: Fiber | null,
  _debugIsCurrentlyTiming?: boolean,
  _debugNeedsRemount?: boolean,

  // Used to verify that the order of hooks does not change between renders.
  _debugHookTypes?: Array<HookType> | null,
|};

用途

Fiber 的设计和属性支持多种用途,主要集中在提高性能、支持并发特性以及优化更新过程。

FiberRoot/FiberRootNode

定义

FiberRootNode 是用来创建 FiberRoot 对象的

// Exported FiberRoot type includes all properties,
// To avoid requiring potentially error-prone :any casts throughout the project.
// Profiling properties are only safe to access in profiling builds (when enableSchedulerTracing is true).
// The types are defined separately within this file to ensure they stay in sync.
// (We don't have to use an inline :any cast when enableSchedulerTracing is disabled.)
export type FiberRoot = {
  ...BaseFiberRootProperties,
  ...ProfilingOnlyFiberRootProperties,
  ...SuspenseCallbackOnlyFiberRootProperties,
  ...
};

type BaseFiberRootProperties = {|
  // The type of root (legacy, batched, concurrent, etc.)
    // export type RootTag = 0 | 1 | 2;                
  tag: RootTag,

  // Any additional information from the host associated with this root.
  // root 节点,render 方法接收的第二个参数
  // 页面上挂载的dom节点, 就是render方法接收的第二个参数
  // 这是根容器的引用,比如DOM节点。
  // 在浏览器环境中,这通常是一个DOM元素,React会将渲染的内容挂载到这个节点上。
  containerInfo: any,
  // Used only by persistent updates.
  // 只有在持久更新中会用到,也就是不支持增量更新的平台, react-dom不会用到 
  pendingChildren: any,
  // The currently active root fiber. This is the mutable root of the tree.
  // 当前应用对应的 Fiber 对象, 是 Root Fiber 
  // 当前树的根节点,就是FiberRoot 
  // 当前正在使用的Fiber树的根节点。Fiber树是React用来表示UI组件树的内部数据结构。
  current: Fiber,

  pingCache: WeakMap<Wakeable, Set<mixed>> | Map<Wakeable, Set<mixed>> | null,

  // A finished work-in-progress HostRoot that's ready to be committed.
  // 已经完成的任务的 FiberRoot 对象,
  // 如果你只有一个 Root,那它永远只可能是这个 Root 对应的 Fiber,或者是 null
  // 在 commit 阶段只会处理这个值对应的任务  
  // 指向已完成的工作树,即已经计算好的Fiber树,等待提交阶段将其更新到DOM。
  finishedWork: Fiber | null,
  // Timeout handle returned by setTimeout. Used to cancel a pending timeout, if
  // it's superseded by a new one.
  // 用于管理异步任务的超时句柄。
  // 通过setTimeout设置的返回内容,如果被新的任务代替,用来取消pending状态的timeout
  // 在任务被挂起的时候通过setTimeout设置的返回内容,用来下一次如果有新的任务挂起时清理还没触发的timeout 
  timeoutHandle: TimeoutHandle | NoTimeout,
  // Top context object, used by renderSubtreeIntoContainer
  // 当前应用程序的上下文信息,通常用于在组件树中传递全局数据。
  // 顶层 context 对象,只有主动调用 renderSubtreeIntoContainer 时才会使用  
  context: Object | null,
  // 下一个将要应用的上下文信息。
  // 在服务器端渲染(SSR)中使用,用于存储尚未完成的子树。
  pendingContext: Object | null,
  // Determines if we should attempt to hydrate on the initial mount
  // 用来确定第一次渲染的时候是否需要融合                              
  +hydrate: boolean,

  // Used by useMutableSource hook to avoid tearing during hydration.
  mutableSourceEagerHydrationData?: Array<
    MutableSource<any> | MutableSourceVersion,
  > | null,

  // Node returned by Scheduler.scheduleCallback. Represents the next rendering
  // task that the root will work on.
  // 调度优先级相关的信息,React使用这些来决定在何时执行更新。
  callbackNode: *,
  callbackPriority: LanePriority,
  // 记录事件发生的时间,用于调度优化。
  eventTimes: LaneMap<number>,
  // 管理任务的过期时间,用于协调任务优先级。
  expirationTimes: LaneMap<number>,

  // 用于任务调度和优先级管理的内部结构。
  pendingLanes: Lanes,
  suspendedLanes: Lanes,
  pingedLanes: Lanes,
  expiredLanes: Lanes,
  mutableReadLanes: Lanes,

  finishedLanes: Lanes,

  entangledLanes: Lanes,
  entanglements: LaneMap<Lanes>,
|};

// The following attributes are only used by interaction tracing builds.
// They enable interactions to be associated with their async work,
// And expose interaction metadata to the React DevTools Profiler plugin.
// Note that these attributes are only defined when the enableSchedulerTracing flag is enabled.
type ProfilingOnlyFiberRootProperties = {|
  interactionThreadID: number,
  memoizedInteractions: Set<Interaction>,
  pendingInteractionMap: Map<Lane | Lanes, Set<Interaction>>,
|};

// The follow fields are only used by enableSuspenseCallback for hydration.
type SuspenseCallbackOnlyFiberRootProperties = {|
  hydrationCallbacks: null | SuspenseHydrationCallbacks,
|};

用途

ReactRootTags

定义

ReactRootTags 是用于标识 React 应用程序的根类型的内部枚举。这些标识在 React 内部用来区分不同类型的渲染环境,比如客户端渲染和服务器渲染。

ReactRootTags 包含以下属性:

LegacyRoot: 这是传统的 React 根,用于兼容旧版的 React 应用。通常在不使用并发特性的应用中会用到。

ConcurrentRoot: 这是用于启用 React 18 的并发特性的新根类型。它支持并发渲染,允许 React 打断渲染工作以响应更高优先级的更新。这是 React 18 的一个重要特性,旨在提升应用的响应速度和流畅度。

export type RootTag = 0 | 1;

export const LegacyRoot = 0;
export const ConcurrentRoot = 1;

用途

ReactRootTags 类型主要在 React 内部使用,特别是在创建 React 应用的根节点时。例如,当你使用 ReactDOM.createRoot 方法时,React 会在内部决定使用哪种 ReactRootTag。对于开发者来说,这种区分通常是透明的,你只需要选择合适的 API(如 createRoot 而不是 render)以利用 React 18 的新特性。

ReactFiberFlags

定义


export type Flags = number;

// Don't change these two values. They're used by React Dev Tools.
// 表示没有任何更新或操作需要对该 Fiber 节点进行。初始状态。
export const NoFlags = /*                      */ 0b00000000000000000000000000;
export const PerformedWork = /*                */ 0b00000000000000000000000001;

// You can change the rest (and add more).
// 表示该 Fiber 节点是新创建的,需要插入到 DOM 中。用于标记需要添加到树中的新组件。
export const Placement = /*                    */ 0b00000000000000000000000010;
// 表示该 Fiber 节点有状态更新,需要重新渲染。用于标记需要更新的组件。
export const Update = /*                       */ 0b00000000000000000000000100;
// 表示该 Fiber 节点需要从 DOM 中移除。用于标记需要删除的组件。
export const Deletion = /*                     */ 0b00000000000000000000001000;
// 用于标记子节点需要被删除的情况。
export const ChildDeletion = /*                */ 0b00000000000000000000010000;
// 用于某些特殊组件,表示需要重置内容。
export const ContentReset = /*                 */ 0b00000000000000000000100000;
// 表示该 Fiber 节点有回调函数需要在 commit 阶段调用。
export const Callback = /*                     */ 0b00000000000000000001000000;
// 表示该 Fiber 节点在渲染过程中捕获了错误。
export const DidCapture = /*                   */ 0b00000000000000000010000000;
// 用于指示需要强制在客户端上重新渲染组件。通常在涉及 SSR(服务器端渲染)或 Hydration 的场景中使用
export const ForceClientRender = /*            */ 0b00000000000000000100000000;
// 表示该 Fiber 节点有关联的 ref 需要更新。
export const Ref = /*                          */ 0b00000000000000001000000000;
// 表示该 Fiber 节点需要在更新之前执行 getSnapshotBeforeUpdate。
export const Snapshot = /*                     */ 0b00000000000000010000000000;
// 表示该 Fiber 节点有 passive effects(如 useEffect 的 cleanup)需要在 commit 之后执行。
export const Passive = /*                      */ 0b00000000000000100000000000;
// 用于标记正在进行的 hydration 操作。
export const Hydrating = /*                    */ 0b00000000000001000000000000;
// 用于标记与组件可见性相关的操作。
export const Visibility = /*                   */ 0b00000000000010000000000000;
// 用于标记需要检查和维护某种一致性状态的情况,比如在 Redux 或者其他全局状态管理方案中使用的场景。
// 确保在组件更新过程中,状态的变动不会导致不一致。
export const StoreConsistency = /*             */ 0b00000000000100000000000000;

// 这是一个组合标志,用于表示在生命周期中可能需要执行的多种效果。
export const LifecycleEffectMask =
  Passive | Update | Callback | Ref | Snapshot | StoreConsistency;

// Union of all commit flags (flags with the lifetime of a particular commit)
// 这是所有提交标志的联合,用于表示在一次提交过程中可能出现的所有效果。
export const HostEffectMask = /*               */ 0b00000000000111111111111111;

// These are not really side effects, but we still reuse this field.
export const Incomplete = /*                   */ 0b00000000001000000000000000;
export const ShouldCapture = /*                */ 0b00000000010000000000000000;
export const ForceUpdateForLegacySuspense = /* */ 0b00000000100000000000000000;
export const DidPropagateContext = /*          */ 0b00000001000000000000000000;
export const NeedsPropagation = /*             */ 0b00000010000000000000000000;
export const Forked = /*                       */ 0b00000100000000000000000000;

// Static tags describe aspects of a fiber that are not specific to a render,
// e.g. a fiber uses a passive effect (even if there are no updates on this particular render).
// This enables us to defer more work in the unmount case,
// since we can defer traversing the tree during layout to look for Passive effects,
// and instead rely on the static flag as a signal that there may be cleanup work.
export const RefStatic = /*                    */ 0b00001000000000000000000000;
export const LayoutStatic = /*                 */ 0b00010000000000000000000000;
export const PassiveStatic = /*                */ 0b00100000000000000000000000;

// These flags allow us to traverse to fibers that have effects on mount
// without traversing the entire tree after every commit for
// double invoking
export const MountLayoutDev = /*               */ 0b01000000000000000000000000;
export const MountPassiveDev = /*              */ 0b10000000000000000000000000;

用途

这些标志位在 React 的协调(Reconciliation)和提交(Commit)阶段被广泛使用。协调阶段主要负责计算哪些节点需要更新、插入或删除,而提交阶段则负责实际执行这些操作,将计算出的变化应用到 DOM 中。

ReactWorkTag

定义

export type WorkTag =
  | 0
  | 1
  | 2
  | 3
  | 4
  | 5
  | 6
  | 7
  | 8
  | 9
  | 10
  | 11
  | 12
  | 13
  | 14
  | 15
  | 16
  | 17
  | 18
  | 19
  | 20
  | 21
  | 22
  | 23
  | 24;
// 表示一个函数组件。函数组件是一个接受props并返回React元素的JavaScript函数。
export const FunctionComponent = 0;
// 表示一个类组件。类组件是通过ES6类语法定义的组件,通常有状态和生命周期方法。
export const ClassComponent = 1;
// 初始状态下的组件,在确定是函数组件还是类组件之前使用。
export const IndeterminateComponent = 2; // Before we know whether it is function or class
// 表示根节点,也就是通过ReactDOM.createRoot()创建的根。
export const HostRoot = 3; // Root of a host tree. Could be nested inside another node.
// HostPortal 用于实现 React Portals。
// Portals 提供了一种将子节点渲染到父组件层次结构以外的 DOM 节点中的方式。
export const HostPortal = 4; // A subtree. Could be an entry point to a different renderer.
// 表示普通的DOM元素,比如<div>、<span>等。
export const HostComponent = 5;
// 表示文本节点,通常是React元素树中的字符串。
export const HostText = 6;
// 表示React Fragment,用于返回多个子元素而不需要额外的DOM节点。
export const Fragment = 7;
// Mode 标签用于标记 React 的模式组件,
// 比如 StrictMode 或者 ConcurrentMode(后者在 React 18 中被合并到默认行为)。
export const Mode = 8;
// 表示一个Context对象的消费者。
export const ContextConsumer = 9;
// 表示一个Context对象的提供者。
export const ContextProvider = 10;
// 表示使用React.forwardRef创建的组件。
export const ForwardRef = 11;
// Profiler 是用于测量组件渲染性能的工具。它允许开发者收集每个渲染的耗时信息。
export const Profiler = 12;
// 表示一个Suspense组件,用于处理异步加载和延迟渲染。
export const SuspenseComponent = 13;
// 表示使用React.memo优化的组件。
export const MemoComponent = 14;
// SimpleMemoComponent 用于标记通过 React.memo 创建的组件,它是一个优化的版本,减少不必要的重渲染。
export const SimpleMemoComponent = 15;
// 表示使用React.lazy动态加载的组件。
export const LazyComponent = 16;
export const IncompleteClassComponent = 17;
export const DehydratedFragment = 18;
export const SuspenseListComponent = 19;
export const FundamentalComponent = 20;
export const ScopeComponent = 21;
export const Block = 22;
// 用于表示需要延迟渲染或隐藏的组件。
export const OffscreenComponent = 23;
export const LegacyHiddenComponent = 24;

用途

这些标签在React的调度器和协调器中发挥作用,帮助React区分不同类型的组件和元素,以便正确地处理更新和渲染。

Update & UpdateQueue

定义

Update类型定义了一个更新对象,用于管理组件状态的更新。该对象主要用于内部调度机制,帮助React在状态更新时进行协调。

export type Update<State> = {|
  // TODO: Temporary field. Will remove this by storing a map of
  // transition -> event time on the root.
  // 表示事件发生的时间戳。这在调度更新时可能被用来确定更新的优先级。
  eventTime: number,
  // 用于区分不同优先级的更新请求。不同的lane可以代表不同的更新路径或优先级。
  lane: Lane,

  // export const UpdateState = 0; 状态更新,例如通过setState引发的更新。
  // export const ReplaceState = 1; 状态替换,将用新的状态替换现有状态。
  // export const ForceUpdate = 2; 强制更新组件,无论状态是否改变。
  // export const CaptureUpdate = 3; 用于捕获更新,通常用于错误边界。
  // 指定更新的内容,值为以上几种  
  tag: 0 | 1 | 2 | 3,
  // 是更新的具体内容。对于setState,这通常是更新函数的第一个参数。
  payload: any,
  // 是一个可选的回调函数,当更新完成后会被调用。setState和render方法可以接收这样的回调。
  // 对应的回调,setState、render 都有 
  callback: (() => mixed) | null,
  // 是一个指向下一个更新对象的指针。这使得更新对象可以形成一个链表,便于按顺序处理多个更新请求。
  next: Update<State> | null,
|};

type SharedQueue<State> = {|
  // 是一个指向Update对象的指针,表示当前待处理的更新链表的头部。
  // 如果pending为null,则表示当前没有待处理的更新。
  // pending指向的Update对象可能是一个链表的头节点,
  // 链表中的每个节点都是一个Update对象,表示一系列需要按顺序处理的更新。
  pending: Update<State> | null,
|};

export type UpdateQueue<State> = {|
  // 每次操作完更新之后的 state                                
  baseState: State,
  // 队列中的第一个 Update                                
  firstBaseUpdate: Update<State> | null,
  // 队列中的最后一个 Update                               
  lastBaseUpdate: Update<State> | null,
  // 是一个SharedQueue对象,包含一个pending属性,用于管理共享的更新队列。
  // 这允许多个更新请求被合并,并以合适的优先级进行处理。
  shared: SharedQueue<State>,
  // 是一个数组,包含需要在更新之后执行的副作用(effects)。
  // 这些副作用可能是由于更新引起的,例如componentDidUpdate或类似的生命周期方法中定义的操作。
  // 如果没有需要执行的副作用,effects可以是null。
  effects: Array<Update<State>> | null,
|};

// 状态更新,例如通过setState引发的更新。
export const UpdateState = 0;
// 状态替换,将用新的状态替换现有状态。
export const ReplaceState = 1;
// 强制更新组件,无论状态是否改变。
export const ForceUpdate = 2;
// 用于捕获更新,通常用于错误边界。
export const CaptureUpdate = 3;

用途

在React内部用于管理复杂的状态更新过程,确保组件以正确的顺序和优先级进行更新。

HookType

定义

export type HookType =
  | 'useState'
  | 'useReducer'
  | 'useContext'
  | 'useRef'
  | 'useEffect'
  | 'useLayoutEffect'
  | 'useCallback'
  | 'useMemo'
  | 'useImperativeHandle'
  | 'useDebugValue'
  | 'useDeferredValue'
  | 'useTransition'
  | 'useMutableSource'
  | 'useOpaqueIdentifier';

用途

Mode

定义

export type TypeOfMode = number;

// 表示没有特别的渲染模式,所有位都为0。
export const NoMode = /*                         */ 0b000000;
// TODO: Remove ConcurrentMode by reading from the root tag instead
// 表示并发模式。启用该模式的标志是最低位为1。
export const ConcurrentMode = /*                 */ 0b000001;
//  表示性能分析模式。启用该模式的标志是第二位为1。
export const ProfileMode = /*                    */ 0b000010;
// 表示调试追踪模式。启用该模式的标志是第三位为1。
export const DebugTracingMode = /*               */ 0b000100;
// 表示严格的遗留模式。启用该模式的标志是第四位为1。
export const StrictLegacyMode = /*               */ 0b001000;
// 表示严格效果模式。启用该模式的标志是第五位为1。
export const StrictEffectsMode = /*              */ 0b010000;
// 表示默认并发更新模式。启用该模式的标志是第六位为1。
export const ConcurrentUpdatesByDefaultMode = /* */ 0b100000;

用途

用于表示不同的渲染模式。这些模式帮助React在不同的环境下优化渲染过程。


TOP