13.React源码学习-commit

commit

首先要标记优先级,因为有一部分优先级的任务已经被提交了,所以需要清楚一些相关的优先级。被提交的任务应该是:

  • 子树中优先级最高的任务
  • 或者外部指定的优先级(flushSync或者retry)

如果 RootFiber 本身也有副作用(一般只有第一次),那么他本身也要加到 effect 链上,放在最后。接下去是三个提交操作,分别是:

  • 提交Snapshot
  • 提交HostComponent的 side effect`
  • 提交所有组件的生命周期
function commitRoot(root: FiberRoot, finishedWork: Fiber): void {
  isWorking = true
  isCommitting = true
  startCommitTimer()

  invariant(
    root.current !== finishedWork,
    'Cannot commit the same tree as before. This is probably a bug ' +
      'related to the return field. This error is likely caused by a bug ' +
      'in React. Please file an issue.',
  )
  const committedExpirationTime = root.pendingCommitExpirationTime
  invariant(
    committedExpirationTime !== NoWork,
    'Cannot commit an incomplete root. This error is likely caused by a ' +
      'bug in React. Please file an issue.',
  )
  root.pendingCommitExpirationTime = NoWork

  const updateExpirationTimeBeforeCommit = finishedWork.expirationTime
  const childExpirationTimeBeforeCommit = finishedWork.childExpirationTime
  const earliestRemainingTimeBeforeCommit =
    updateExpirationTimeBeforeCommit === NoWork ||
    (childExpirationTimeBeforeCommit !== NoWork &&
      childExpirationTimeBeforeCommit < updateExpirationTimeBeforeCommit)
      ? childExpirationTimeBeforeCommit
      : updateExpirationTimeBeforeCommit
  markCommittedPriorityLevels(root, earliestRemainingTimeBeforeCommit)

  let prevInteractions: Set<Interaction> = (null: any)

  // Reset this to null before calling lifecycles
  ReactCurrentOwner.current = null

  let firstEffect
  if (finishedWork.effectTag > PerformedWork) {
    // A fiber's effect list consists only of its children, not itself. So if
    // the root has an effect, we need to add it to the end of the list. The
    // resulting list is the set that would belong to the root's parent, if
    // it had one; that is, all the effects in the tree including the root.
    if (finishedWork.lastEffect !== null) {
      finishedWork.lastEffect.nextEffect = finishedWork
      firstEffect = finishedWork.firstEffect
    } else {
      firstEffect = finishedWork
    }
  } else {
    // There is no effect on the root.
    firstEffect = finishedWork.firstEffect
  }

  prepareForCommit(root.containerInfo)

  // Invoke instances of getSnapshotBeforeUpdate before mutation.
  nextEffect = firstEffect
  startCommitSnapshotEffectsTimer()
  while (nextEffect !== null) {
    let didError = false
    let error
    if (__DEV__) {
      invokeGuardedCallback(null, commitBeforeMutationLifecycles, null)
      if (hasCaughtError()) {
        didError = true
        error = clearCaughtError()
      }
    } else {
      try {
        commitBeforeMutationLifecycles()
      } catch (e) {
        didError = true
        error = e
      }
    }
    if (didError) {
      invariant(
        nextEffect !== null,
        'Should have next effect. This error is likely caused by a bug ' +
          'in React. Please file an issue.',
      )
      captureCommitPhaseError(nextEffect, error)
      // Clean-up
      if (nextEffect !== null) {
        nextEffect = nextEffect.nextEffect
      }
    }
  }
  stopCommitSnapshotEffectsTimer()

  nextEffect = firstEffect
  startCommitHostEffectsTimer()
  while (nextEffect !== null) {
    let didError = false
    let error
    if (__DEV__) {
      invokeGuardedCallback(null, commitAllHostEffects, null)
      if (hasCaughtError()) {
        didError = true
        error = clearCaughtError()
      }
    } else {
      try {
        commitAllHostEffects()
      } catch (e) {
        didError = true
        error = e
      }
    }
    if (didError) {
      invariant(
        nextEffect !== null,
        'Should have next effect. This error is likely caused by a bug ' +
          'in React. Please file an issue.',
      )
      captureCommitPhaseError(nextEffect, error)
      // Clean-up
      if (nextEffect !== null) {
        nextEffect = nextEffect.nextEffect
      }
    }
  }
  stopCommitHostEffectsTimer()

  resetAfterCommit(root.containerInfo)

  root.current = finishedWork

  nextEffect = firstEffect
  startCommitLifeCyclesTimer()
  while (nextEffect !== null) {
    let didError = false
    let error
    if (__DEV__) {
      invokeGuardedCallback(
        null,
        commitAllLifeCycles,
        null,
        root,
        committedExpirationTime,
      )
      if (hasCaughtError()) {
        didError = true
        error = clearCaughtError()
      }
    } else {
      try {
        commitAllLifeCycles(root, committedExpirationTime)
      } catch (e) {
        didError = true
        error = e
      }
    }
    if (didError) {
      invariant(
        nextEffect !== null,
        'Should have next effect. This error is likely caused by a bug ' +
          'in React. Please file an issue.',
      )
      captureCommitPhaseError(nextEffect, error)
      if (nextEffect !== null) {
        nextEffect = nextEffect.nextEffect
      }
    }
  }

  isCommitting = false
  isWorking = false
  stopCommitLifeCyclesTimer()
  stopCommitTimer()
  onCommitRoot(finishedWork.stateNode)

  const updateExpirationTimeAfterCommit = finishedWork.expirationTime
  const childExpirationTimeAfterCommit = finishedWork.childExpirationTime
  const earliestRemainingTimeAfterCommit =
    updateExpirationTimeAfterCommit === NoWork ||
    (childExpirationTimeAfterCommit !== NoWork &&
      childExpirationTimeAfterCommit < updateExpirationTimeAfterCommit)
      ? childExpirationTimeAfterCommit
      : updateExpirationTimeAfterCommit
  if (earliestRemainingTimeAfterCommit === NoWork) {
    // If there's no remaining work, we can clear the set of already failed
    // error boundaries.
    legacyErrorBoundariesThatAlreadyFailed = null
  }
  onCommit(root, earliestRemainingTimeAfterCommit)

  // profiler 相关
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,188评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,464评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,562评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,893评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,917评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,708评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,430评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,342评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,801评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,976评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,115评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,804评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,458评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,008评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,135评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,365评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,055评论 2 355