diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp index 3646ea0a62e..eb167544e7a 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp @@ -618,6 +618,15 @@ void FabricMountingManager::executeMount( std::vector cppUpdateOverflowInsetMountItems; std::vector cppUpdateEventEmitterMountItems; + // Views created by this transaction, with the state and event emitter their + // Create item already passes to Java. Their Insert doesn't need to pass them + // again. + struct CreatedView { + const State* state; + const EventEmitter* eventEmitter; + }; + std::unordered_map createdViews; + { std::lock_guard allocatedViewsLock(allocatedViewsMutex_); @@ -657,6 +666,9 @@ void FabricMountingManager::executeMount( if (shouldCreateView) { cppCommonMountItems.push_back( CppMountItem::CreateMountItem(newChildShadowView)); + createdViews[newChildShadowView.tag] = CreatedView{ + .state = newChildShadowView.state.get(), + .eventEmitter = newChildShadowView.eventEmitter.get()}; } else { allocatedView->second.state = AllocatedViewState::Mounted; } @@ -756,6 +768,13 @@ void FabricMountingManager::executeMount( break; } case ShadowViewMutation::Insert: { + auto createdView = createdViews.find(newChildShadowView.tag); + bool createdWithSameState = createdView != createdViews.end() && + createdView->second.state == newChildShadowView.state.get(); + bool createdWithSameEventEmitter = + createdView != createdViews.end() && + createdView->second.eventEmitter == + newChildShadowView.eventEmitter.get(); if (!isVirtual) { // Insert item cppCommonMountItems.push_back( @@ -804,7 +823,7 @@ void FabricMountingManager::executeMount( } // State - if (newChildShadowView.state) { + if (newChildShadowView.state && !createdWithSameState) { (maintainMutationOrder ? cppCommonMountItems : cppUpdateStateMountItems) .push_back( @@ -845,13 +864,16 @@ void FabricMountingManager::executeMount( } // EventEmitter - // On insert we always update the event emitter, as we do not pass - // it in when preallocating views - (maintainMutationOrder ? cppCommonMountItems - : cppUpdateEventEmitterMountItems) - .push_back( - CppMountItem::UpdateEventEmitterMountItem( - mutation.newChildShadowView)); + // On insert we update the event emitter, as we do not pass it in + // when preallocating views. A view created by this transaction + // already got it with its Create item. + if (!createdWithSameEventEmitter) { + (maintainMutationOrder ? cppCommonMountItems + : cppUpdateEventEmitterMountItems) + .push_back( + CppMountItem::UpdateEventEmitterMountItem( + mutation.newChildShadowView)); + } break; }