auto build()

in ComponentKit/Core/Render/CKRenderHelpers.mm [166:226]


    auto build(id<CKComponentProtocol> component,
               CKTreeNode *parent,
               CKTreeNode *_Nullable previousParent,
               const CKBuildComponentTreeParams &params,
               BOOL parentHasStateUpdate) -> void
    {
      RCCAssertNotNil(component, @"component cannot be nil");
      RCCAssertNotNil(parent, @"parent cannot be nil");

      // Check if the component already has a tree node.
      CKTreeNode *node = component.treeNode;

      [node linkComponent:component toParent:parent inScopeRoot:params.scopeRoot];

      unsigned int numberOfChildren = [component numberOfChildren];
      if (numberOfChildren == 0) {
        return;
      }

      // The assumption was that if there was no previous parent this node couldn't
      // possibly have a state update. In reality this can happen if the previous generation
      // didn't contain a render component (thus the second phase wouldn't have been performed
      // and component aren't linked). A state update on a first generation's non reusable
      // component introducing a reusable component would lead to an incorrect `parentHasStateUpdate`
      // value.
      id previousParentOrComponent = params.previousScopeRoot.hasRenderComponentInTree == NO ? (id)component : previousParent;

      // Update the `parentHasStateUpdate` param for Faster state/props updates.
      // TODO: Share this value with the value precomputed in the scope
      parentHasStateUpdate = parentHasStateUpdate ||
      (params.buildTrigger == CKBuildTriggerStateUpdate &&
       CKRender::componentHasStateUpdate(node,
                                         previousParentOrComponent,
                                         params.buildTrigger,
                                         params.stateUpdates));

      // If there is a node, we update the parents' pointers to the next level in the tree.
      if (node) {
        parent = node;
        previousParent = [previousParent childForComponentKey:[node componentKey]];

        // Report information to `debugAnalyticsListener`.
        if (numberOfChildren == 1 && params.shouldCollectTreeNodeCreationInformation) {
          [params.scopeRoot.analyticsListener didBuildTreeNodeForPrecomputedChild:component
                                                                             node:node
                                                                           parent:parent
                                                                           params:params
                                                             parentHasStateUpdate:parentHasStateUpdate];
        }
      }

      for (int i=0; i<numberOfChildren; i++) {
        auto const childComponent = (id<CKComponentProtocol>)[component childAtIndex:i];
        if (childComponent) {
          [childComponent buildComponentTree:parent
                              previousParent:previousParent
                                      params:params
                        parentHasStateUpdate:parentHasStateUpdate];
        }
      }
    }