Skip to content

Commit

Permalink
Add alwaysThrottleRetries flag (#26685)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
acdlite authored and kassens committed Apr 21, 2023
1 parent 5d8f7fa commit c43c0d6
Show file tree
Hide file tree
Showing 12 changed files with 45 additions and 6 deletions.
6 changes: 5 additions & 1 deletion packages/react-reconciler/src/ReactFiberWorkLoop.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
enableTransitionTracing,
useModernStrictMode,
disableLegacyContext,
alwaysThrottleRetries,
} from 'shared/ReactFeatureFlags';
import ReactSharedInternals from 'shared/ReactSharedInternals';
import is from 'shared/objectIs';
Expand Down Expand Up @@ -1115,7 +1116,10 @@ function finishConcurrentRender(
workInProgressTransitions,
);
} else {
if (includesOnlyRetries(lanes)) {
if (
includesOnlyRetries(lanes) &&
(alwaysThrottleRetries || exitStatus === RootSuspended)
) {
// This render only included retries, no updates. Throttle committing
// retries so that we don't show too many loading states too quickly.
const msUntilTimeout =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1779,10 +1779,28 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await resolveText('B');
expect(ReactNoop).toMatchRenderedOutput(<span prop="Loading..." />);

// Restart and render the complete content. The tree will finish but we
// won't commit the result yet because the fallback appeared recently.
// Restart and render the complete content.
await waitForAll(['A', 'B']);
expect(ReactNoop).toMatchRenderedOutput(<span prop="Loading..." />);

if (gate(flags => flags.alwaysThrottleRetries)) {
// Correct behavior:
//
// The tree will finish but we won't commit the result yet because the fallback appeared recently.
expect(ReactNoop).toMatchRenderedOutput(<span prop="Loading..." />);
} else {
// Old behavior, gated until this rolls out at Meta:
//
// TODO: Because this render was the result of a retry, and a fallback
// was shown recently, we should suspend and remain on the fallback for
// little bit longer. We currently only do this if there's still
// remaining fallbacks in the tree, but we should do it for all retries.
expect(ReactNoop).toMatchRenderedOutput(
<>
<span prop="A" />
<span prop="B" />
</>,
);
}
});
assertLog([]);
expect(ReactNoop).toMatchRenderedOutput(
Expand Down
2 changes: 2 additions & 0 deletions packages/shared/ReactFeatureFlags.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ export const diffInCommitPhase = __EXPERIMENTAL__;

export const enableAsyncActions = __EXPERIMENTAL__;

export const alwaysThrottleRetries = true;

// -----------------------------------------------------------------------------
// Chopping Block
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import typeof * as DynamicFlagsType from 'ReactNativeInternalFeatureFlags';

export const enableUseRefAccessWarning = __VARIANT__;
export const enableDeferRootSchedulingToMicrotask = __VARIANT__;
export const alwaysThrottleRetries = __VARIANT__;

// Flow magic to verify the exports of this file match the original version.
((((null: any): ExportsType): DynamicFlagsType): ExportsType);
7 changes: 5 additions & 2 deletions packages/shared/forks/ReactFeatureFlags.native-fb.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ import * as dynamicFlags from 'ReactNativeInternalFeatureFlags';

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

// The rest of the flags are static for better dead code elimination.
export const enableDebugTracing = false;
Expand Down
2 changes: 2 additions & 0 deletions packages/shared/forks/ReactFeatureFlags.native-oss.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,7 @@ export const enableDeferRootSchedulingToMicrotask = true;
export const diffInCommitPhase = true;
export const enableAsyncActions = false;

export const alwaysThrottleRetries = true;

// Flow magic to verify the exports of this file match the original version.
((((null: any): ExportsType): FeatureFlagsType): ExportsType);
2 changes: 2 additions & 0 deletions packages/shared/forks/ReactFeatureFlags.test-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,7 @@ export const enableDeferRootSchedulingToMicrotask = true;
export const diffInCommitPhase = true;
export const enableAsyncActions = false;

export const alwaysThrottleRetries = true;

// Flow magic to verify the exports of this file match the original version.
((((null: any): ExportsType): FeatureFlagsType): ExportsType);
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,7 @@ export const enableDeferRootSchedulingToMicrotask = true;
export const diffInCommitPhase = true;
export const enableAsyncActions = false;

export const alwaysThrottleRetries = true;

// Flow magic to verify the exports of this file match the original version.
((((null: any): ExportsType): FeatureFlagsType): ExportsType);
2 changes: 2 additions & 0 deletions packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,7 @@ export const enableDeferRootSchedulingToMicrotask = true;
export const diffInCommitPhase = true;
export const enableAsyncActions = false;

export const alwaysThrottleRetries = true;

// Flow magic to verify the exports of this file match the original version.
((((null: any): ExportsType): FeatureFlagsType): ExportsType);
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.www-dynamic.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const enableCustomElementPropertySupport = __VARIANT__;
export const enableDeferRootSchedulingToMicrotask = __VARIANT__;
export const diffInCommitPhase = __VARIANT__;
export const enableAsyncActions = __VARIANT__;
export const alwaysThrottleRetries = __VARIANT__;

// Enable this flag to help with concurrent mode debugging.
// It logs information to the console about React scheduling, rendering, and commit phases.
Expand Down
1 change: 1 addition & 0 deletions packages/shared/forks/ReactFeatureFlags.www.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const {
enableDeferRootSchedulingToMicrotask,
diffInCommitPhase,
enableAsyncActions,
alwaysThrottleRetries,
} = dynamicFeatureFlags;

// On WWW, __EXPERIMENTAL__ is used for a new modern build.
Expand Down
1 change: 1 addition & 0 deletions scripts/flow/xplat.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@
declare module 'ReactNativeInternalFeatureFlags' {
declare export var enableUseRefAccessWarning: boolean;
declare export var enableDeferRootSchedulingToMicrotask: boolean;
declare export var alwaysThrottleRetries: boolean;
}

0 comments on commit c43c0d6

Please sign in to comment.