React DOM createRoot() updateContainer()
在v18.0之后,DOM.render()
方法已经被归为Legacy,取而代之的是DOM.createRoot()
方法。
位置:react-reconciler\src\ReactFiberReconciler.new.js
createRoot()
export function createRoot(
container: Container,
options?: CreateRootOptions,
): RootType {
// 判断container有效性
invariant(
isValidContainerLegacy(container),
'createRoot(...): Target container is not a DOM element.',
);
warnIfReactDOMContainerInDEV(container);
// 下述注水相关可选项会在未来被删除...
// 注水可选项
const hydrate = options != null && options.hydrate === true;
// 注水是否有回调
const hydrationCallbacks =
(options != null && options.hydrationOptions) || null;
// 可更改sources
const mutableSources =
(options != null &&
options.hydrationOptions != null &&
options.hydrationOptions.mutableSources) ||
null;
// 严格模式flag
const isStrictMode = options != null && options.unstable_strictMode === true;
// 默认同步更新,null
let concurrentUpdatesByDefaultOverride = null;
if (allowConcurrentByDefault) {
concurrentUpdatesByDefaultOverride =
options != null && options.unstable_concurrentUpdatesByDefault != null
? options.unstable_concurrentUpdatesByDefault
: null;
}
// createContainer 创建一个FiberRoot,每个属性的意义可以参考上一篇文章
const root = createContainer(
container,
ConcurrentRoot,
hydrate,
hydrationCallbacks,
isStrictMode,
concurrentUpdatesByDefaultOverride,
);
// 标记这个container为根,具体就是把这个container设置为内部实例key
markContainerAsRoot(root.current, container);
// 根container元素,要么是container本身要么是container的父节点
const rootContainerElement =
container.nodeType === COMMENT_NODE ? container.parentNode : container;
// 给根container元素加上所有支持的事件监听
listenToAllSupportedEvents(rootContainerElement);
// 下述在未来会被删除...
if (mutableSources) {
for (let i = 0; i < mutableSources.length; i++) {
const mutableSource = mutableSources[i];
// 将所有可更改sources注册,即将所有可更改sources传入fiberRoot的mutableSourceEagerHydrationData数组中
registerMutableSourceForHydration(root, mutableSource);
}
}
// 将创建的root传入私有变量_internalRoot中并返回
return new ReactDOMRoot(root);
}
updateContainer()
export function updateContainer(
element: ReactNodeList,
container: OpaqueRoot,
parentComponent: ?React$Component<any, any>,
callback: ?Function,
): Lane {
if (__DEV__) {
onScheduleRoot(container, element);
}
// 当前可更改的fibeRoot
const current = container.current;
// 保存事件的开始时间
const eventTime = requestEventTime();
// 请求一个更新车道lane,requestUpdateLane方法后续再考
const lane = requestUpdateLane(current);
if (enableSchedulingProfiler) {
// 在Performance接口中标记--schedule-render-{当前lane}用于性能分析
markRenderScheduled(lane);
}
// 查找子树的context,如果当前fiberRoot没有context则赋值,如有则保存在pendingContext中
const context = getContextForSubtree(parentComponent);
if (container.context === null) {
container.context = context;
} else {
container.pendingContext = context;
}
if (__DEV__) {
if (
ReactCurrentFiberIsRendering &&