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.ReactElement
。React.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
是一个具有 type
、props
和 key
属性的对象,这些属性用来描述一个 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组件树(如在自定义的
shouldComponentUpdate
、React.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>
null
或undefined
:这两者表示什么都不渲染。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 的组件。无论多深,所有的消费者都会重新渲染,当Provider
的value
发生变化时。典型的用法是在组件树的顶层使用
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>
);
}
注意
RefObject
的current
属性是可变的,但更改它不会触发组件重新渲染。在函数组件中,
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在不同的环境下优化渲染过程。