diff --git a/packages/react-native/ReactCommon/react/renderer/viewtransition/ViewTransitionModule.cpp b/packages/react-native/ReactCommon/react/renderer/viewtransition/ViewTransitionModule.cpp index 5892e345131..f070bfce3bf 100644 --- a/packages/react-native/ReactCommon/react/renderer/viewtransition/ViewTransitionModule.cpp +++ b/packages/react-native/ReactCommon/react/renderer/viewtransition/ViewTransitionModule.cpp @@ -7,6 +7,7 @@ #include "ViewTransitionModule.h" +#include #include #include #include @@ -93,7 +94,20 @@ void ViewTransitionModule::applyViewTransitionName( if (auto it = oldPseudoElementNodesRepository_.find(name); it != oldPseudoElementNodesRepository_.end()) { - oldPseudoElementNodes_[name] = it->second.node; + // Find the pseudo element created from this specific source tag + auto& pseudoElementsBySourceTag = it->second; + auto innerIt = pseudoElementsBySourceTag.find(tag); + if (innerIt != pseudoElementsBySourceTag.end()) { + oldPseudoElementNodes_[name] = innerIt->second.node; + } else if (!pseudoElementsBySourceTag.empty()) { + // Fallback to first available entry for this name + oldPseudoElementNodes_[name] = + pseudoElementsBySourceTag.begin()->second.node; + } + } else { + LOG(WARNING) + << "applyViewTransitionName: old pseudo element shadow node doesn't exist for name " + << name; } } else { @@ -158,7 +172,7 @@ void ViewTransitionModule::createViewTransitionInstance( if (!forNextTransition) { oldPseudoElementNodes_[name] = pseudoElementNode; } - oldPseudoElementNodesRepository_[name] = InactivePseudoElement{ + oldPseudoElementNodesRepository_[name][view.tag] = InactivePseudoElement{ .node = pseudoElementNode, .sourceTag = view.tag}; } } @@ -222,7 +236,12 @@ std::optional ViewTransitionModule::pullTransaction( auto tag = mutation.oldChildShadowView.tag; for (auto it = oldPseudoElementNodesRepository_.begin(); it != oldPseudoElementNodesRepository_.end();) { - if (it->second.sourceTag == tag) { + auto& pseudoElementsBySourceTag = it->second; + if (auto innerIt = pseudoElementsBySourceTag.find(tag); + innerIt != pseudoElementsBySourceTag.end()) { + pseudoElementsBySourceTag.erase(innerIt); + } + if (pseudoElementsBySourceTag.empty()) { it = oldPseudoElementNodesRepository_.erase(it); } else { ++it; diff --git a/packages/react-native/ReactCommon/react/renderer/viewtransition/ViewTransitionModule.h b/packages/react-native/ReactCommon/react/renderer/viewtransition/ViewTransitionModule.h index 44878c24b68..ad28dce6a69 100644 --- a/packages/react-native/ReactCommon/react/renderer/viewtransition/ViewTransitionModule.h +++ b/packages/react-native/ReactCommon/react/renderer/viewtransition/ViewTransitionModule.h @@ -124,7 +124,8 @@ class ViewTransitionModule : public UIManagerViewTransitionDelegate, // pseudo-element nodes created for entering nodes, to be copied into // oldPseudoElementNodes_ during the next applyViewTransitionName call. // Mutable because pullTransaction (const) needs to erase unmounted entries. - mutable std::unordered_map oldPseudoElementNodesRepository_{}; + mutable std::unordered_map> + oldPseudoElementNodesRepository_{}; LayoutMetrics captureLayoutMetricsFromRoot(const ShadowNode &shadowNode);