From cd5d74518becb3355519373211d2f54ff7dbd208 Mon Sep 17 00:00:00 2001 From: Nick Lefever Date: Thu, 5 Jun 2025 11:43:03 -0700 Subject: [PATCH] Fix image loading on props change without layout invalidation (#51791) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/51791 On iOS the shadow node was expecting a layout call for every clone. With `passChildrenWhenCloningPersistedNodes` components may have the image source updated without layout being called on it due to the re-use of the previous layout data thanks to the improved handling of layout invalidation. This diff triggers the image request as soon as possible if the cloned shadow node has a clean layout. The request will be made as soon as the image manager is set on the shadow node. Changelog: [iOS][Fixed] - Fix RCTImageComponentView image loading after source props change with no layout invalidation Reviewed By: NickGerleman, sammy-SC Differential Revision: D75919671 fbshipit-source-id: 8b92a9c63b6ff4a62c7eb7b0dbe18dd2be989b81 --- .../components/image/ImageShadowNode.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/react-native/ReactCommon/react/renderer/components/image/ImageShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/image/ImageShadowNode.cpp index 23b1429eddd..49001347ce5 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/image/ImageShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/image/ImageShadowNode.cpp @@ -20,6 +20,22 @@ const char ImageComponentName[] = "Image"; void ImageShadowNode::setImageManager(const SharedImageManager& imageManager) { ensureUnsealed(); imageManager_ = imageManager; + + // TODO: T226624691 Improve image request creation to avoid double requests + // The image manager is set when the component descriptor adopts the shadow + // node. For instances where the shadow node was cloned without dirtying the + // layout, if the image source was changed we have to initiate the image + // request now since there is no guarantee that layout will run for the shadow + // node at a later time. + if (getIsLayoutClean()) { + auto sources = getConcreteProps().sources; + auto layoutMetric = getLayoutMetrics(); + if (sources.size() <= 1 || + (layoutMetric.frame.size.width > 0 && + layoutMetric.frame.size.height > 0)) { + updateStateIfNeeded(); + } + } } void ImageShadowNode::updateStateIfNeeded() {