diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java index 67e28885cea..a158825274a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java @@ -105,40 +105,53 @@ public class MountItemDispatcher { if (ReactNativeFeatureFlags.forceBatchingMountItemsOnAndroid()) { mInDispatch = true; - } - final boolean didDispatchItems; - try { - didDispatchItems = dispatchMountItems(); - } catch (Throwable e) { - mReDispatchCounter = 0; - throw e; - } finally { - // Clean up after running dispatchMountItems - even if an exception was thrown - mInDispatch = false; - } - - // We call didDispatchMountItems regardless of whether we actually dispatched anything, since - // NativeAnimatedModule relies on this for executing any animations that may have been scheduled - mItemDispatchListener.didDispatchMountItems(); - - // Decide if we want to try reentering - if (mReDispatchCounter < 10 && didDispatchItems) { - // Executing twice in a row is normal. Only log after that point. - if (mReDispatchCounter > 2) { - ReactSoftExceptionLogger.logSoftException( - TAG, - new ReactNoCrashSoftException( - "Re-dispatched " - + mReDispatchCounter - + " times. This indicates setState (?) is likely being called too many times" - + " during mounting.")); + try { + boolean didDispatchItems = true; + // Dispatch as many mount items as we find. Some mount items might + // trigger state updates that trigger more mount items. This will + // process them correctly. + while (didDispatchItems) { + didDispatchItems = dispatchMountItems(); + } + } finally { + mInDispatch = false; + } + } else { + final boolean didDispatchItems; + try { + didDispatchItems = dispatchMountItems(); + } catch (Throwable e) { + mReDispatchCounter = 0; + throw e; + } finally { + // Clean up after running dispatchMountItems - even if an exception was thrown + mInDispatch = false; } - mReDispatchCounter++; - tryDispatchMountItems(); + // We call didDispatchMountItems regardless of whether we actually dispatched anything, since + // NativeAnimatedModule relies on this for executing any animations that may have been + // scheduled + mItemDispatchListener.didDispatchMountItems(); + + // Decide if we want to try reentering + if (mReDispatchCounter < 10 && didDispatchItems) { + // Executing twice in a row is normal. Only log after that point. + if (mReDispatchCounter > 2) { + ReactSoftExceptionLogger.logSoftException( + TAG, + new ReactNoCrashSoftException( + "Re-dispatched " + + mReDispatchCounter + + " times. This indicates setState (?) is likely being called too many times" + + " during mounting.")); + } + + mReDispatchCounter++; + tryDispatchMountItems(); + } + mReDispatchCounter = 0; } - mReDispatchCounter = 0; } @UiThread