CKBuildComponentResult CKBuildComponent()

in ComponentKit/Core/CKBuildComponent.mm [102:164]


CKBuildComponentResult CKBuildComponent(CK::NonNull<CKComponentScopeRoot *> previousRoot,
                                        const CKComponentStateUpdateMap &stateUpdates,
                                        NS_NOESCAPE CKComponent *(^componentFactory)(void),
                                        CKBuildTrigger buildTrigger,
                                        CKReflowTrigger reflowTrigger,
                                        RCComponentCoalescingMode coalescingMode)
{
  RCCAssertNotNil(componentFactory, @"Must have component factory to build a component");
  auto const globalConfig = CKReadGlobalConfig();

  auto const analyticsListener = [previousRoot analyticsListener];
  auto const shouldCollectTreeNodeCreationInformation = [analyticsListener shouldCollectTreeNodeCreationInformation:previousRoot];

  CKThreadLocalComponentScope threadScope(previousRoot,
                                          stateUpdates,
                                          buildTrigger,
                                          shouldCollectTreeNodeCreationInformation,
                                          globalConfig.alwaysBuildRenderTree,
                                          coalescingMode,
                                          /* enforce CKComponent */ YES,
                                          globalConfig.disableRenderToNilInCoalescedCompositeComponents);

  [analyticsListener willBuildComponentTreeWithScopeRoot:previousRoot
                                            buildTrigger:buildTrigger
                                            stateUpdates:stateUpdates];
#if CK_ASSERTIONS_ENABLED
  const CKComponentContext<CKComponentCreationValidationContext> validationContext([[CKComponentCreationValidationContext alloc] initWithSource:CKComponentCreationValidationSourceBuild]);
#endif
  auto const component = componentFactory();

  // Build the component tree if we have a render component in the hierarchy.
  if ([threadScope.newScopeRoot hasRenderComponentInTree] || globalConfig.alwaysBuildRenderTree) {
    CKBuildComponentTreeParams params = {
      .scopeRoot = threadScope.newScopeRoot,
      .previousScopeRoot = previousRoot,
      .stateUpdates = stateUpdates,
      .treeNodeDirtyIds = threadScope.treeNodeDirtyIds,
      .buildTrigger = buildTrigger,
      .systraceListener = threadScope.systraceListener,
      .shouldCollectTreeNodeCreationInformation = shouldCollectTreeNodeCreationInformation,
      .coalescingMode = coalescingMode,
    };

    // Build the component tree from the render function.
    CKRender::ComponentTree::Root::build(component, params);
  }

  auto newScopeRoot = threadScope.newScopeRoot;
  auto const boundsAnimation = CKBuildComponentHelpers::boundsAnimationFromPreviousScopeRoot(newScopeRoot, previousRoot);

  [analyticsListener didBuildComponentTreeWithScopeRoot:newScopeRoot
                                           buildTrigger:buildTrigger
                                           stateUpdates:stateUpdates
                                              component:component
                                        boundsAnimation:boundsAnimation];
  [newScopeRoot setRootComponent:component];
  return {
    .component = component,
    .scopeRoot = newScopeRoot,
    .boundsAnimation = boundsAnimation,
    .buildTrigger = buildTrigger,
  };
}