React|React before mutation阶段
commit阶段分为三个部分
- before mutation阶段
- mutation阶段
- layout阶段
主要都是在commitRootImpl函数内进行调用
if (firstEffect !== null) {
// 保存之前的优先级,以同步优先级执行,执行完毕后恢复之前优先级
const previousLanePriority = getCurrentUpdateLanePriority();
setCurrentUpdateLanePriority(SyncLanePriority);
// 将当前上下文标记为CommitContext,作为commit阶段的标志
const prevExecutionContext = executionContext;
executionContext |= CommitContext;
const prevInteractions = pushInteractions(root);
// 在调用生命周期之前将此重置为 null
ReactCurrentOwner.current = null;
// The commit phase is broken into several sub-phases. We do a separate pass
// of the effect list for each phase: all mutation effects come before all
// layout effects, and so on.// The first phase a "before mutation" phase. We use this phase to read the
// state of the host tree right before we mutate it. This is where
// getSnapshotBeforeUpdate is called.
focusedInstanceHandle = prepareForCommit(root.containerInfo);
shouldFireAfterActiveInstanceBlur = false;
nextEffect = firstEffect;
do {
if (__DEV__) {
//....开发环境下调用
invokeGuardedCallback(null, commitBeforeMutationEffects, null);
if (hasCaughtError()) {
invariant(nextEffect !== null, 'Should be working on an effect.');
const error = clearCaughtError();
captureCommitPhaseError(nextEffect, error);
nextEffect = nextEffect.nextEffect;
}
} else {
try {
// 调用commitBeforeMutationEffects
commitBeforeMutationEffects();
} catch (error) {
invariant(nextEffect !== null, 'Should be working on an effect.');
captureCommitPhaseError(nextEffect, error);
nextEffect = nextEffect.nextEffect;
}
}
} while (nextEffect !== null);
//....
}
invokeGuardedCallback 开发环境下调用commitBeforeMutationEffects函数
function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) {
hasError = false;
caughtError = null;
invokeGuardedCallbackImpl$1.apply(reporter, arguments);
}
commitBeforeMutationEffects 调用before mutation主要函数
function commitBeforeMutationEffects() {
while (nextEffect !== null) {
const current = nextEffect.alternate;
if (!shouldFireAfterActiveInstanceBlur && focusedInstanceHandle !== null) {
// ...focus blur相关
if ((nextEffect.effectTag & Deletion) !== NoEffect) {
if (doesFiberContain(nextEffect, focusedInstanceHandle)) {
shouldFireAfterActiveInstanceBlur = true;
beforeActiveInstanceBlur();
}
} else {
// TODO: Move this out of the hot path using a dedicated effect tag.
if (
nextEffect.tag === SuspenseComponent &&
isSuspenseBoundaryBeingHidden(current, nextEffect) &&
doesFiberContain(nextEffect, focusedInstanceHandle)
) {
shouldFireAfterActiveInstanceBlur = true;
beforeActiveInstanceBlur();
}
}
}const effectTag = nextEffect.effectTag;
if ((effectTag & Snapshot) !== NoEffect) {
setCurrentDebugFiberInDEV(nextEffect);
// 调用getSnapshotBeforeUpdate
commitBeforeMutationEffectOnFiber(current, nextEffect);
resetCurrentDebugFiberInDEV();
}
// 调度useEffect
if ((effectTag & Passive) !== NoEffect) {
// If there are passive effects, schedule a callback to flush at
// the earliest opportunity.
if (!rootDoesHavePassiveEffects) {
rootDoesHavePassiveEffects = true;
scheduleCallback(NormalSchedulerPriority, () => {
flushPassiveEffects();
return null;
});
}
}
nextEffect = nextEffect.nextEffect;
}
}
commitBeforeMutationEffectOnFiber 主要判断组件类型,如果是类组件就执行getSnapshotBeforeUpdate生命周期
function commitBeforeMutationLifeCycles(
current: Fiber | null,
finishedWork: Fiber,
): void {
switch (finishedWork.tag) {
case FunctionComponent:
case ForwardRef:
case SimpleMemoComponent:
case Block: {
return;
}
case ClassComponent: {
if (finishedWork.effectTag & Snapshot) {
if (current !== null) {
const prevProps = current.memoizedProps;
const prevState = current.memoizedState;
const instance = finishedWork.stateNode;
// We could update instance props and state here,
// but instead we rely on them being set during last render.
// TODO: revisit this when we implement resuming.
if (__DEV__) {
// ....
}
// 调用getSnapshotBeforeUpdate生命周期
const snapshot = instance.getSnapshotBeforeUpdate(
finishedWork.elementType === finishedWork.type
? prevProps
: resolveDefaultProps(finishedWork.type, prevProps),
prevState,
);
if (__DEV__) {
// ....
}
instance.__reactInternalSnapshotBeforeUpdate = snapshot;
}
}
return;
}
case HostRoot: {
if (supportsMutation) {
if (finishedWork.effectTag & Snapshot) {
const root = finishedWork.stateNode;
clearContainer(root.containerInfo);
}
}
return;
}
case HostComponent:
case HostText:
case HostPortal:
case IncompleteClassComponent:
// Nothing to do for these component types
return;
}
invariant(
false,
'This unit of work tag should not have side-effects. This error is ' +
'likely caused by a bug in React. Please file an issue.',
);
}
新版生命周期。
文章图片
总结 这节主要学习before mutation阶段函数调用流程
- commitRootImpl是commit阶段主要函数,调用commitBeforeMutationEffects
- commitBeforeMutationEffects主要功能是:执行commitBeforeMutationEffectOnFiber和通过flushPassiveEffects调度useEffect
- commitBeforeMutationEffectOnFiber通过判断组件类型主要来执行类组件getSnapshotBeforeUpdate生命周期函数
文章图片
推荐阅读
- 服务器框架设计模式|多线程Reactor分析,从性能,客户接入量方向
- 自我提升(项目中React及JavaScript遇到问题记录)
- typescript使用入门及react+ts实战
- 我发现了华点(vue规定用普通函数定义方法,为什么react又要我用箭头函数!)
- 基于 React + Redux/Mobx 搞定复杂项目状态管理|无密分享
- react|京东高层变动(徐雷升集团总裁,刘强东关注年轻CEO培养)
- React中的renderProps和childrenProps
- react|react框架入门
- React|Redux中间件及其开发者工具
- Vue|vue和react脚手架rem适配配置