From 5dbe02c9cffcee699a6ccc05e5204f355bfd5e84 Mon Sep 17 00:00:00 2001 From: Ricky Hanlon Date: Mon, 25 Mar 2024 14:16:05 -0400 Subject: [PATCH 1/2] Fix gating for alwaysThrottleDisappearingFallbacks --- .../src/__tests__/ReactSuspenseWithNoopRenderer-test.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js index f52c33887c2..9c32a588b54 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js @@ -1846,7 +1846,14 @@ describe('ReactSuspenseWithNoopRenderer', () => { await resolveText('B'); await waitForPaint(['B']); - if (gate(flags => flags.alwaysThrottleRetries)) { + if ( + // This behavior only applies if both flags are enabled. + gate( + flags => + flags.alwaysThrottleDisappearingFallbacks && + flags.alwaysThrottleRetries, + ) + ) { // B should not commit yet. Even though it's been a long time since its // fallback was shown, it hasn't been long since A appeared. So B's // appearance is throttled to reduce jank. From fc72ca90750ff04f98d78230497d4e8b4174ccfd Mon Sep 17 00:00:00 2001 From: Ricky Hanlon Date: Mon, 25 Mar 2024 14:28:11 -0400 Subject: [PATCH 2/2] Fix alwaysThrottleDisappearingFallbacks --- .../react-reconciler/src/ReactFiberWorkLoop.js | 5 ++++- .../ReactSuspenseWithNoopRenderer-test.js | 14 ++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index 152b0b460b2..9b4aba8189b 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -38,6 +38,7 @@ import { useModernStrictMode, disableLegacyContext, alwaysThrottleRetries, + alwaysThrottleDisappearingFallbacks, enableInfiniteRenderLoopDetection, } from 'shared/ReactFeatureFlags'; import ReactSharedInternals from 'shared/ReactSharedInternals'; @@ -1128,7 +1129,9 @@ function finishConcurrentRender( } else { if ( includesOnlyRetries(lanes) && - (alwaysThrottleRetries || exitStatus === RootSuspended) + (alwaysThrottleRetries || + (alwaysThrottleDisappearingFallbacks && exitStatus === RootCompleted) || + exitStatus === RootSuspended) ) { // This render only included retries, no updates. Throttle committing // retries so that we don't show too many loading states too quickly. diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js index 9c32a588b54..20ea18c0b02 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js @@ -1757,7 +1757,13 @@ describe('ReactSuspenseWithNoopRenderer', () => { // Restart and render the complete content. await waitForAll(['A', 'B']); - if (gate(flags => flags.alwaysThrottleRetries)) { + if ( + gate( + flags => + flags.alwaysThrottleDisappearingFallbacks || + flags.alwaysThrottleRetries, + ) + ) { // Correct behavior: // // The tree will finish but we won't commit the result yet because the fallback appeared recently. @@ -1848,11 +1854,7 @@ describe('ReactSuspenseWithNoopRenderer', () => { if ( // This behavior only applies if both flags are enabled. - gate( - flags => - flags.alwaysThrottleDisappearingFallbacks && - flags.alwaysThrottleRetries, - ) + gate(flags => flags.alwaysThrottleDisappearingFallbacks) ) { // B should not commit yet. Even though it's been a long time since its // fallback was shown, it hasn't been long since A appeared. So B's