下面简单的写一篇关于React渲染和一个hooks用法的示例:
React主要是react和react-dom这两个库,节点主要放在react-reconciler中去处理。
简单画的一张图:
React-dom:
程序最简单的解析是从react-dom里面的Render函数入手,Render-> legacyRenderSubtreeIntoContainer函数查看reactFiberRoot是否存在,不存在则创建FiberRoot将其挂载root._internalRoot上,判断如果有回调则执行回调,
接下来因为是初始化,不需要batch所以执行 unbatchedUpdates(() => {
updateContainer(children, fiberRoot, parentComponent, callback);
});
如果已存在FIberRoot就直接执行updateContainer:
通过const lane = requestUpdateLane(current);获取FiberNode的更新标记
如果是子组件则通过父组件获取子组件的context,
const context = getContextForSubtree(parentComponent);
创建一个更新const update = createUpdate(eventTime, lane);
将当前节点的更新压入更新队列,enqueueUpdate。
最后将这个更新更新到FiberRoot节点上。
React useState:
从ReactHooks文件入手,我们可以看到在里面导出了hooks的接口,接下来就是要在ReactFIberHooks中去实现这些hooks.
ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;
以mount的useState为例
useState<S>(
initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
currentHookNameInDev = 'useState';
mountHookTypesDev();
const prevDispatcher = ReactCurrentDispatcher.current;
ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnMountInDEV;
try {
return mountState(initialState);
} finally {
ReactCurrentDispatcher.current = prevDispatcher;
}
},
在mountState函数中做创建hooks,并设置hook的初始状态和更新队列,最后调用dispatchAction来更新Fiber的hook,dispatchAction中创建一个新的update并挂载到hook的queue.next上准备下一次更新。
执行 const root = scheduleUpdateOnFiber(fiber, lane, eventTime);
const root = markUpdateLaneFromFiberToRoot(fiber, lane);
将Fiber放入更新列表中,更新至FiberRoot中。