当前 Fiber
是一个在开发环境下追踪当前正在渲染的 Fiber 节点的全局对象。
这句话是阿里的千问说的
主要用于 DevTools 和 错误边界( Error Boundaries ) 等调试功能,在盛昌环境通常会被 Tree Shaking 移除或置为空。
ReactCurrentFiber 是一个导出的对象:
- current 属性 : 动态指向当前执行上下文对应的 Fiber 节点
一、作用
1.核心作用
- 提供执行上下文: 在 React 执行更新(如渲染、事件处理、 Hooks 调用)时,
ReactCurrentFiber.current标识了 当前组件对应的 Fiber 节点 - 协调过程( Reconciliation )的锚点,在 Fiber 树遍历过程中:
- 进入一个 Fiber 前, React 会将其赋值给
ReactCurrentFiber.current - 处理该节点的更新、副作用(如
useEffect) 或子节点 - 离开节点时,重置
current(通常为父节点 或null)
- 进入一个 Fiber 前, React 会将其赋值给
2.与 Fiber 关系
- Fiber 树 : React 内部表示组件树链条结构,每个节点包含组件信息、状态、副作用等
- ReactCurrentFiber : 充当指针,动态标记遍历过程中的“当前位置”,类似遍历链表时的临时变量
3.为什么需要 ReactCurrentFiber
- 上下文隔离 : 确保异步操作(如事件回调、 Hooks )中仍能追踪到原始渲染上下文
- 性能优化 : 避免递归传递 Fiber 参数,通过全局指针快速访问
- 协调过程解耦 : 将 Fiber 遍历与具体操作(如 Hooks 处理)分离,提升代码可维护性
二、 当前 Fiber
export let current: Fiber | null = null;
三、当前是否正在渲染
export let isRendering: boolean = false;
四、在开发中获取当前 Fiber 所有者的名称或返回空
export function getCurrentFiberOwnerNameInDevOrNull(): string | null {
if (__DEV__) {
if (current === null) {
return null;
}
const owner = current._debugOwner;
if (owner != null) {
// 由 getComponentNamerFormFiber 文件提供实现方法
return getComponentNameFromOwner(owner);
}
}
return null;
}
五、设置当前的 fiber
export function setCurrentFiber(fiber: Fiber | null) {
if (__DEV__) {
ReactSharedInternals.getCurrentStack =
fiber === null ? null : getCurrentFiberStackInDev;
isRendering = false;
}
current = fiber;
}
六、在开发环境中使用 Fiber 运行
export function runWithFiberInDEV<A0, A1, A2, A3, A4, T>(
fiber: null | Fiber,
callback: (A0, A1, A2, A3, A4) => T,
arg0: A0,
arg1: A1,
arg2: A2,
arg3: A3,
arg4: A4,
): T {
if (__DEV__) {
const previousFiber = current;
setCurrentFiber(fiber);
try {
if (fiber !== null && fiber._debugTask) {
return fiber._debugTask.run(
callback.bind(null, arg0, arg1, arg2, arg3, arg4),
);
}
return callback(arg0, arg1, arg2, arg3, arg4);
} finally {
setCurrentFiber(previousFiber);
}
}
// These errors should never make it into a build so we don't need to encode them in codes.json
// 这些错误永远不应该出现在构建中,所以我们不需要在 codes.json 中对它们进行编码
throw new Error(
'runWithFiberInDEV should never be called in production. This is a bug in React.',
);
}
七、重置当前的 Fibber
export function resetCurrentFiber() {
if (__DEV__) {
ReactSharedInternals.getCurrentStack = null;
isRendering = false;
}
current = null;
}
八、设置是否正渲染
export function setIsRendering(rendering: boolean) {
if (__DEV__) {
isRendering = rendering;
}
}
九、获取是否正渲染
export function getIsRendering(): void | boolean {
if (__DEV__) {
return isRendering;
}
}
十、工具
1. 在开发中获取当前 Fiber 堆栈
function getCurrentFiberStackInDev(): string {
if (__DEV__) {
if (current === null) {
return '';
}
// Safe because if current fiber exists, we are reconciling,
// 安全,因为如果当前 fiber 存在,我们正在进行协调,
// and it is guaranteed to be the work-in-progress version.
// 并且它保证是正在处理的版本。
// TODO: The above comment is not actually true. We might be
// TODO: 上述注释实际上不完全正确。
// in a commit phase or preemptive set state callback.
// 我们可能处于提交阶段或抢占设置状态回调中。
return getOwnerStackByFiberInDev(current);
}
return '';
}