Appearance
Offscreen
这是一个基本不怎么使用的组件,但是在 React 内部很多组价都是基于其处理子节点的显示状态的。
创建
在 React 暴露的方法中,并没有找到 Offscreen 组件的定义。 其只是暴露了一个 unstable_Offscreen => export const REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen'); 用于我们判断子节点的类型是否是 Offscreen 组件。 所以我们无法通过 <React.Offscreen /> 去创建一个 Offscreen 组件。也不能通过 React.createElement(REACT_OFFSCREEN_TYPE) 去创建一个 Offscreen 组件。
其中有两个关键的入参 :
- mode : 控制子节点的显示状态
但是我们还是需要关注一下这个组件的对象。
组件对象
其创建函数为 createFiberFromOffscreen(offscreenProps, mode, NoLanes, null);
js
export function createFiberFromOffscreen(
pendingProps: OffscreenProps,
mode: TypeOfMode,
lanes: Lanes,
key: null | string
) {
const fiber = createFiber(OffscreenComponent, pendingProps, key, mode);
fiber.elementType = REACT_OFFSCREEN_TYPE;
fiber.lanes = lanes;
const primaryChildInstance: OffscreenInstance = {
isHidden: false,
};
fiber.stateNode = primaryChildInstance;
return fiber;
}
const primaryChildProps: OffscreenProps = {
mode: "visible",
children: primaryChildren,
};Fiber 结构
js
const OffscreenFiber = {
tag: OffscreenComponent, // 22
key: key,
elementType: Symbol.for("react.offscreen"),
type: null,
stateNode: { isHidden: false | true },
pendingProps: pendingProps, // { mode : 'hide' | 'visible' , children : ReactNode }
alternate: null,
// 在 Hide 状态下 才会存在这些参数,在 visible 状态下 不存在
memoizedState: {
baseLanes: renderLanes,
cachePool: getSuspendedCache(),
transitions: null,
},
};beginWork 阶段
因为 Offscreen 组件 lane 优先级是比较低的,所以在 beginWork 阶段,其子节点的渲染优先级也会被跳过,从而导致子节点中高优先级的 lane 不会被执行。为了解决这个问题,React 内部会在 beginWork 阶段,对 Offscreen 组件每次渲染时,如果 renderLanes 中不包含
OffscreenLane的时候,会将执行的 lane 缓存到OffscreenLane.stateNode.baseLane中,等到处理OffscreenLane的时候一起处理。Offscreen 组件在
mode : 'hide'的时候其子节点会执行渲染么?
在 Render 阶段, 其不管是 visible 还是 hide 都会执行。 在 Commit 阶段,只有
