# completeWork

# FunctionalComponent & FunctionalComponentLazy

什么也不做

# ClassComponent & ClassComponentLazy

如果又提供老的context api,则推出context

# HostRoot

推出containertopLevelContextObject

如果是初次渲染,增加PlacementeffectTag,因为要把内容放入dom

# HostComponent

如果不是第一次渲染,则updateComponent

updateHostComponent = function(
  current: Fiber,
  workInProgress: Fiber,
  type: Type,
  newProps: Props,
  rootContainerInstance: Container,
) {
  const oldProps = current.memoizedProps
  if (oldProps === newProps) {
    return
  }

  const instance: Instance = workInProgress.stateNode
  const currentHostContext = getHostContext()
  const updatePayload = prepareUpdate(
    instance,
    type,
    oldProps,
    newProps,
    rootContainerInstance,
    currentHostContext,
  )
  workInProgress.updateQueue = (updatePayload: any)
  if (updatePayload) {
    markUpdate(workInProgress)
  }
}

prepareUpdate做的就是我们常说的diff算法,调用的是diffProperties

如果是第一次渲染,根据是否要hydrate使用不同的方法创建dom对象,并执行finalizeInitialChildren,这个方法会创建事件监听等内容。

TODO: finalizeInitialChildren.md TODO: diffProperties.md TODO: hydrate.md

# HostText

HostComponent差不多

updateHostText = function(
  current: Fiber,
  workInProgress: Fiber,
  oldText: string,
  newText: string,
) {
  // If the text differs, mark it as an update. All the work in done in commitWork.
  if (oldText !== newText) {
    markUpdate(workInProgress)
  }
}

markUpdate就是增加UpdateeffectTag

# HostPortal

推出HostContainerupdateHostContainerDOM平台是个空方法

# ContextProvider

推出context

# 其他

都没什么操作

function completeWork(
  current: Fiber | null,
  workInProgress: Fiber,
  renderExpirationTime: ExpirationTime,
): Fiber | null {
  const newProps = workInProgress.pendingProps

  switch (workInProgress.tag) {
    case FunctionalComponent:
    case FunctionalComponentLazy:
      break
    case ClassComponent: {
      const Component = workInProgress.type
      if (isLegacyContextProvider(Component)) {
        popLegacyContext(workInProgress)
      }
      break
    }
    case ClassComponentLazy: {
      const Component = getResultFromResolvedThenable(workInProgress.type)
      if (isLegacyContextProvider(Component)) {
        popLegacyContext(workInProgress)
      }
      break
    }
    case HostRoot: {
      popHostContainer(workInProgress)
      popTopLevelLegacyContextObject(workInProgress)
      const fiberRoot = (workInProgress.stateNode: FiberRoot)
      if (fiberRoot.pendingContext) {
        fiberRoot.context = fiberRoot.pendingContext
        fiberRoot.pendingContext = null
      }
      if (current === null || current.child === null) {
        popHydrationState(workInProgress)
        workInProgress.effectTag &= ~Placement
      }
      updateHostContainer(workInProgress)
      break
    }
    case HostComponent: {
      popHostContext(workInProgress)
      const rootContainerInstance = getRootHostContainer()
      const type = workInProgress.type
      if (current !== null && workInProgress.stateNode != null) {
        updateHostComponent(
          current,
          workInProgress,
          type,
          newProps,
          rootContainerInstance,
        )

        if (current.ref !== workInProgress.ref) {
          markRef(workInProgress)
        }
      } else {
        if (!newProps) {
          invariant(
            workInProgress.stateNode !== null,
            'We must have new props for new mounts. This error is likely ' +
              'caused by a bug in React. Please file an issue.',
          )
          // This can happen when we abort work.
          break
        }

        const currentHostContext = getHostContext()
        let wasHydrated = popHydrationState(workInProgress)
        if (wasHydrated) {
          if (
            prepareToHydrateHostInstance(
              workInProgress,
              rootContainerInstance,
              currentHostContext,
            )
          ) {
            markUpdate(workInProgress)
          }
        } else {
          let instance = createInstance(
            type,
            newProps,
            rootContainerInstance,
            currentHostContext,
            workInProgress,
          )

          appendAllChildren(instance, workInProgress)

          if (
            finalizeInitialChildren(
              instance,
              type,
              newProps,
              rootContainerInstance,
              currentHostContext,
            )
          ) {
            markUpdate(workInProgress)
          }
          workInProgress.stateNode = instance
        }

        if (workInProgress.ref !== null) {
          // If there is a ref on a host node we need to schedule a callback
          markRef(workInProgress)
        }
      }
      break
    }
    case HostText: {
      let newText = newProps
      if (current && workInProgress.stateNode != null) {
        const oldText = current.memoizedProps
        // If we have an alternate, that means this is an update and we need
        // to schedule a side-effect to do the updates.
        updateHostText(current, workInProgress, oldText, newText)
      } else {
        if (typeof newText !== 'string') {
          invariant(
            workInProgress.stateNode !== null,
            'We must have new props for new mounts. This error is likely ' +
              'caused by a bug in React. Please file an issue.',
          )
          // This can happen when we abort work.
        }
        const rootContainerInstance = getRootHostContainer()
        const currentHostContext = getHostContext()
        let wasHydrated = popHydrationState(workInProgress)
        if (wasHydrated) {
          if (prepareToHydrateHostTextInstance(workInProgress)) {
            markUpdate(workInProgress)
          }
        } else {
          workInProgress.stateNode = createTextInstance(
            newText,
            rootContainerInstance,
            currentHostContext,
            workInProgress,
          )
        }
      }
      break
    }
    case ForwardRef:
    case ForwardRefLazy:
      break
    case PlaceholderComponent:
      break
    case Fragment:
      break
    case Mode:
      break
    case Profiler:
      break
    case HostPortal:
      popHostContainer(workInProgress)
      updateHostContainer(workInProgress)
      break
    case ContextProvider:
      // Pop provider fiber
      popProvider(workInProgress)
      break
    case ContextConsumer:
      break
    // Error cases
    case IndeterminateComponent:
      invariant(
        false,
        'An indeterminate component should have become determinate before ' +
          'completing. This error is likely caused by a bug in React. Please ' +
          'file an issue.',
      )
    // eslint-disable-next-line no-fallthrough
    default:
      invariant(
        false,
        'Unknown unit of work tag. This error is likely caused by a bug in ' +
          'React. Please file an issue.',
      )
  }

  return null
}

下一节请看: