Skip to content

Commit c43c0d6

Browse files
acdlitekassens
authored andcommitted
Add alwaysThrottleRetries flag (#26685)
This puts the change introduced by #26611 behind a flag until Meta is able to roll it out. Disabling the flag reverts back to the old behavior, where retries are throttled if there's still data remaining in the tree, but not if all the data has finished loading. The new behavior is still enabled in the public builds.
1 parent 5d8f7fa commit c43c0d6

12 files changed

+45
-6
lines changed

packages/react-reconciler/src/ReactFiberWorkLoop.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import {
3939
enableTransitionTracing,
4040
useModernStrictMode,
4141
disableLegacyContext,
42+
alwaysThrottleRetries,
4243
} from 'shared/ReactFeatureFlags';
4344
import ReactSharedInternals from 'shared/ReactSharedInternals';
4445
import is from 'shared/objectIs';
@@ -1115,7 +1116,10 @@ function finishConcurrentRender(
11151116
workInProgressTransitions,
11161117
);
11171118
} else {
1118-
if (includesOnlyRetries(lanes)) {
1119+
if (
1120+
includesOnlyRetries(lanes) &&
1121+
(alwaysThrottleRetries || exitStatus === RootSuspended)
1122+
) {
11191123
// This render only included retries, no updates. Throttle committing
11201124
// retries so that we don't show too many loading states too quickly.
11211125
const msUntilTimeout =

packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1779,10 +1779,28 @@ describe('ReactSuspenseWithNoopRenderer', () => {
17791779
await resolveText('B');
17801780
expect(ReactNoop).toMatchRenderedOutput(<span prop="Loading..." />);
17811781

1782-
// Restart and render the complete content. The tree will finish but we
1783-
// won't commit the result yet because the fallback appeared recently.
1782+
// Restart and render the complete content.
17841783
await waitForAll(['A', 'B']);
1785-
expect(ReactNoop).toMatchRenderedOutput(<span prop="Loading..." />);
1784+
1785+
if (gate(flags => flags.alwaysThrottleRetries)) {
1786+
// Correct behavior:
1787+
//
1788+
// The tree will finish but we won't commit the result yet because the fallback appeared recently.
1789+
expect(ReactNoop).toMatchRenderedOutput(<span prop="Loading..." />);
1790+
} else {
1791+
// Old behavior, gated until this rolls out at Meta:
1792+
//
1793+
// TODO: Because this render was the result of a retry, and a fallback
1794+
// was shown recently, we should suspend and remain on the fallback for
1795+
// little bit longer. We currently only do this if there's still
1796+
// remaining fallbacks in the tree, but we should do it for all retries.
1797+
expect(ReactNoop).toMatchRenderedOutput(
1798+
<>
1799+
<span prop="A" />
1800+
<span prop="B" />
1801+
</>,
1802+
);
1803+
}
17861804
});
17871805
assertLog([]);
17881806
expect(ReactNoop).toMatchRenderedOutput(

packages/shared/ReactFeatureFlags.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ export const diffInCommitPhase = __EXPERIMENTAL__;
124124

125125
export const enableAsyncActions = __EXPERIMENTAL__;
126126

127+
export const alwaysThrottleRetries = true;
128+
127129
// -----------------------------------------------------------------------------
128130
// Chopping Block
129131
//

packages/shared/forks/ReactFeatureFlags.native-fb-dynamic.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import typeof * as DynamicFlagsType from 'ReactNativeInternalFeatureFlags';
2222

2323
export const enableUseRefAccessWarning = __VARIANT__;
2424
export const enableDeferRootSchedulingToMicrotask = __VARIANT__;
25+
export const alwaysThrottleRetries = __VARIANT__;
2526

2627
// Flow magic to verify the exports of this file match the original version.
2728
((((null: any): ExportsType): DynamicFlagsType): ExportsType);

packages/shared/forks/ReactFeatureFlags.native-fb.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ import * as dynamicFlags from 'ReactNativeInternalFeatureFlags';
1717

1818
// We destructure each value before re-exporting to avoid a dynamic look-up on
1919
// the exports object every time a flag is read.
20-
export const {enableUseRefAccessWarning, enableDeferRootSchedulingToMicrotask} =
21-
dynamicFlags;
20+
export const {
21+
enableUseRefAccessWarning,
22+
enableDeferRootSchedulingToMicrotask,
23+
alwaysThrottleRetries,
24+
} = dynamicFlags;
2225

2326
// The rest of the flags are static for better dead code elimination.
2427
export const enableDebugTracing = false;

packages/shared/forks/ReactFeatureFlags.native-oss.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,5 +75,7 @@ export const enableDeferRootSchedulingToMicrotask = true;
7575
export const diffInCommitPhase = true;
7676
export const enableAsyncActions = false;
7777

78+
export const alwaysThrottleRetries = true;
79+
7880
// Flow magic to verify the exports of this file match the original version.
7981
((((null: any): ExportsType): FeatureFlagsType): ExportsType);

packages/shared/forks/ReactFeatureFlags.test-renderer.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,5 +75,7 @@ export const enableDeferRootSchedulingToMicrotask = true;
7575
export const diffInCommitPhase = true;
7676
export const enableAsyncActions = false;
7777

78+
export const alwaysThrottleRetries = true;
79+
7880
// Flow magic to verify the exports of this file match the original version.
7981
((((null: any): ExportsType): FeatureFlagsType): ExportsType);

packages/shared/forks/ReactFeatureFlags.test-renderer.native.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,7 @@ export const enableDeferRootSchedulingToMicrotask = true;
7272
export const diffInCommitPhase = true;
7373
export const enableAsyncActions = false;
7474

75+
export const alwaysThrottleRetries = true;
76+
7577
// Flow magic to verify the exports of this file match the original version.
7678
((((null: any): ExportsType): FeatureFlagsType): ExportsType);

packages/shared/forks/ReactFeatureFlags.test-renderer.www.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,5 +77,7 @@ export const enableDeferRootSchedulingToMicrotask = true;
7777
export const diffInCommitPhase = true;
7878
export const enableAsyncActions = false;
7979

80+
export const alwaysThrottleRetries = true;
81+
8082
// Flow magic to verify the exports of this file match the original version.
8183
((((null: any): ExportsType): FeatureFlagsType): ExportsType);

packages/shared/forks/ReactFeatureFlags.www-dynamic.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export const enableCustomElementPropertySupport = __VARIANT__;
2727
export const enableDeferRootSchedulingToMicrotask = __VARIANT__;
2828
export const diffInCommitPhase = __VARIANT__;
2929
export const enableAsyncActions = __VARIANT__;
30+
export const alwaysThrottleRetries = __VARIANT__;
3031

3132
// Enable this flag to help with concurrent mode debugging.
3233
// It logs information to the console about React scheduling, rendering, and commit phases.

0 commit comments

Comments
 (0)