const reactDOMRoot = ReactDOM.unstable_createRoot(document.getElementById('root')); 创建一个reactDomRoot
createRoot()--> return new ReactDOMRoot(container, options);
function ReactDOMRoot(container: Container, options: void | RootOptions) {
this._internalRoot = createRootImpl(container, ConcurrentRoot /* 2 */, options);// 创建一个fiberRoot对象, 并将其挂载到this._internalRoot之上
}
function createRootImpl(
container: Container,
tag: RootTag,
options: void | RootOptions,
) {
...服务端相关
const root = createContainer(container, tag, hydrate, hydrationCallbacks); // FiberRoot
markContainerAsRoot(root.current, container); // container['__reactContainer$' + randomKey;] = root.current;
const containerNodeType = container.nodeType;
if (enableEagerRootListeners) {
const rootContainerElement =
container.nodeType === COMMENT_NODE/**注释节点 nodetype == 8 */ ? container.parentNode : container;
listenToAllSupportedEvents(rootContainerElement);// 注册事件监听 多种事件 冒泡捕获,是否可以preventdefault()...
}
...
return root;
}
createContainer()-->createFiberRoot()
export function createFiberRoot(
containerInfo: any,
tag: RootTag,
hydrate: boolean,
hydrationCallbacks: null | SuspenseHydrationCallbacks,
): FiberRoot {
const root: FiberRoot = (new FiberRootNode(containerInfo, tag, hydrate): any);
if (enableSuspenseCallback) {
root.hydrationCallbacks = hydrationCallbacks;
}
// Cyclic construction. This cheats the type system right now because
// stateNode is any.
const uninitializedFiber = createHostRootFiber(tag);//createFiber(HostRoot, null, null, mode); -->new FiberNode(tag, pendingProps, key, mode)
root.current = uninitializedFiber;
uninitializedFiber.stateNode = root;
initializeUpdateQueue(uninitializedFiber); // 初始化updateQueue
return root;
}
reactDOMRoot.render();
ReactDOMRoot.prototype.render = ReactDOMBlockingRoot.prototype.render = function(
children: ReactNodeList,
): void {
const root = this._internalRoot;
...
updateContainer(children, root, null, null);
};
updateContainer
export function updateContainer(
element: ReactNodeList,
container: OpaqueRoot,
parentComponent: ?React$Component<any, any>,
callback: ?Function,
): Lane {
if (__DEV__) {
onScheduleRoot(container, element); // root ,children </ App> rootElements.set(root, children);
}
const current = container.current; //FiberNode
const eventTime = requestEventTime(); // now()
...
const lane = requestUpdateLane(current);
if (enableSchedulingProfiler) {
markRenderScheduled(lane); // performance.mark
}
const context = getContextForSubtree(parentComponent); // const emptyContextObject = {};
if (container.context === null) {
container.context = context;
} else {
container.pendingContext = context;
}
...
const update = createUpdate(eventTime, lane); //Update
// Caution: React DevTools currently depends on this property
// being called "element".
update.payload = {element}; // element = <App />
...
}
enqueueUpdate(current, update); // current HostFiberRoot ==> fiber.updateQueue.shared.pending = update update.next=update
scheduleUpdateOnFiber(current, lane, eventTime); // schedular入口
return lane;
}
scheduleUpdateOnFiber
export function scheduleUpdateOnFiber(
fiber: Fiber,
lane: Lane,
eventTime: number,
) {
...
const root = markUpdateLaneFromFiberToRoot(fiber, lane); // fiber.stateNode;
// Mark that the root has a pending update.
markRootUpdated(root, lane, eventTime);
...
// TODO: requestUpdateLanePriority also reads the priority. Pass the
// priority as an argument to that function and this one.
const priorityLevel = getCurrentPriorityLevel();
if (lane === SyncLane) {
...
} else {
// Schedule a discrete update but only if it's not Sync.
...
// Schedule other updates after in case the callback is sync.
ensureRootIsScheduled(root, eventTime); // root.callbackPriority = newCallbackPriority; root.callbackNode = newCallbackNode -->scheduleCallback;
...
}
...
}