in ComponentKit/Core/Render/CKRenderHelpers.mm [101:144]
static auto reusePreviousComponentForSingleChild(CKTreeNode *node,
id<CKRenderWithChildComponentProtocol> component,
__strong id<CKComponentProtocol> *childComponent,
CKTreeNode *parent,
CKTreeNode *previousParent,
const CKBuildComponentTreeParams ¶ms,
BOOL parentHasStateUpdate,
CKRenderDidReuseComponentBlock didReuseBlock) -> BOOL {
// If there is no previous parent or no childComponent, we bail early.
if (previousParent == nil || childComponent == nullptr) {
return NO;
}
// Disable any sort of reuse when environmental changes
if (params.buildTrigger & CKBuildTriggerEnvironmentUpdate) {
return NO;
}
if (params.buildTrigger & CKBuildTriggerStateUpdate) {
// State update branch - only state updates or coalesced state & props update.
// Check if the tree node is not dirty (not in a branch of a state update).
auto const dirtyNodeId = params.treeNodeDirtyIds.find(node.nodeIdentifier);
if (dirtyNodeId == params.treeNodeDirtyIds.end()) {
// We reuse the component without checking `shouldComponentUpdate:` in the following conditions:
// 1. The component is not dirty (on a state update branch)
// 2. No direct parent has a state update
// 3. Not a coalesced state & props update.
if (!parentHasStateUpdate &&
(params.buildTrigger & CKBuildTriggerPropsUpdate) == 0) {
// Faster state update optimizations.
return CKRenderInternal::reusePreviousComponent(component, childComponent, node, parent, previousParent, params, didReuseBlock);
}
// We fallback to the props update optimization in the follwing case:
// - The component is not dirty, but the parent has a state update or tree props were updated.
return (CKRenderInternal::reusePreviousComponentIfComponentsAreEqual(component, childComponent, node, parent, previousParent, params, didReuseBlock));
}
} else if (params.buildTrigger & CKBuildTriggerPropsUpdate) {
// Will be used for coalesced props & state updates too.
return CKRenderInternal::reusePreviousComponentIfComponentsAreEqual(component, childComponent, node, parent, previousParent, params, didReuseBlock);
}
return NO;
}