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,
};
}