mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Implement potential fix for mounting errors during synchronous state updates (v2)
Summary: Changelog: [internal] This is a new attempt at fixing mounting errors during synchronous state updates after what we tried in https://github.com/facebook/react-native/pull/44015. That fix didn't work because `dispatchMountItems` actually makes a copy of the mount items that it's going to process, so when we added the mount items to the list they were actually not being picked up by the current processing. This changes the fix to call `dispatchMountItems` as many times as needed, while there are mount items to process in the list. Reviewed By: sammy-SC Differential Revision: D57107212 fbshipit-source-id: 46988a71daae15d70399258f850653046d0790ff
This commit is contained in:
committed by
Facebook GitHub Bot
parent
958f8e2bb5
commit
fd299509df
+43
-30
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user