@samitouri / QOS-React-2 / commits / d000261eef

[Tracks] Annotate devtools.performanceIssue for Cascading Updates in DEV (#34961)

Alex Hunt committed Nov 4, 2025 at 17:07 UTC d000261eef6109c332a1880e92836856473f6a39
8 files changed +28
packages/react-reconciler/src/ReactFiberPerformanceTrack.js
+15
@@ -36,6 +36,7 @@ import {
36 import {
37 enableProfilerTimer,
38 enableGestureTransition,
39 + enablePerformanceIssueReporting,
40 } from 'shared/ReactFeatureFlags';
41
42 const supportsUserTiming =
@@ -203,6 +204,15 @@ const reusableComponentOptions: PerformanceMeasureOptions = {
204
205 const reusableChangedPropsEntry = ['Changed Props', ''];
206
207 +const reusableCascadingUpdateIssue = {
208 + name: 'React: Cascading Update',
209 + severity: 'warning',
210 + description:
211 + 'A cascading update is an update that is triggered during an ongoing render. This can lead to performance issues.',
212 + learnMoreUrl:
213 + 'https://react.dev/reference/dev-tools/react-performance-tracks#cascading-updates',
214 +};
215 +
216 const DEEP_EQUALITY_WARNING =
217 'This component received deeply equal props. It might benefit from useMemo or the React Compiler in its owner.';
218
@@ -761,6 +771,11 @@ export function logBlockingStart(
771 },
772 },
773 };
774 + if (enablePerformanceIssueReporting && isSpawnedUpdate) {
775 + // $FlowFixMe[prop-missing] - detail is untyped
776 + measureOptions.detail.devtools.performanceIssue =
777 + reusableCascadingUpdateIssue;
778 + }
779
780 if (debugTask) {
781 debugTask.run(
packages/shared/ReactFeatureFlags.js
+5
@@ -232,6 +232,11 @@ export const enableProfilerTimer = __PROFILE__;
232 // All calls should also be gated on enableProfilerTimer.
233 export const enableComponentPerformanceTrack: boolean = true;
234
235 +// Enables annotating of React performance track events with `performanceIssue`
236 +// metadata, to more prominently highlight performance issues to users
237 +// (initially, an experimental feature in React Native).
238 +export const enablePerformanceIssueReporting: boolean = false;
239 +
240 // Adds user timing marks for e.g. state updates, suspense, and work loop stuff,
241 // for an experimental timeline tool.
242 export const enableSchedulingProfiler: boolean =
packages/shared/forks/ReactFeatureFlags.native-fb.js
+2
@@ -83,6 +83,8 @@ export const enableDefaultTransitionIndicator: boolean = true;
83 export const ownerStackLimit = 1e4;
84 export const enableComponentPerformanceTrack: boolean =
85 __PROFILE__ && dynamicFlags.enableComponentPerformanceTrack;
86 +export const enablePerformanceIssueReporting: boolean =
87 + enableComponentPerformanceTrack;
88
89 // Flow magic to verify the exports of this file match the original version.
90 ((((null: any): ExportsType): FeatureFlagsType): ExportsType);
packages/shared/forks/ReactFeatureFlags.native-oss.js
+1
@@ -42,6 +42,7 @@ export const enablePostpone: boolean = false;
42 export const enableReactTestRendererWarning: boolean = false;
43 export const enableRetryLaneExpiration: boolean = false;
44 export const enableComponentPerformanceTrack: boolean = true;
45 +export const enablePerformanceIssueReporting: boolean = false;
46 export const enableSchedulingProfiler: boolean =
47 !enableComponentPerformanceTrack && __PROFILE__;
48 export const enableScopeAPI: boolean = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.js
+1
@@ -16,6 +16,7 @@ export const enableProfilerTimer: boolean = __PROFILE__;
16 export const enableProfilerCommitHooks: boolean = __PROFILE__;
17 export const enableProfilerNestedUpdatePhase: boolean = __PROFILE__;
18 export const enableComponentPerformanceTrack: boolean = true;
19 +export const enablePerformanceIssueReporting: boolean = false;
20 export const enableUpdaterTracking: boolean = false;
21 export const enableLegacyCache: boolean = __EXPERIMENTAL__;
22 export const enableAsyncIterableChildren: boolean = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js
+1
@@ -41,6 +41,7 @@ export const enableReactTestRendererWarning = false;
41 export const enableRetryLaneExpiration = false;
42 export const enableSchedulingProfiler = __PROFILE__;
43 export const enableComponentPerformanceTrack = false;
44 +export const enablePerformanceIssueReporting = false;
45 export const enableScopeAPI = false;
46 export const enableEagerAlternateStateNodeCleanup = true;
47 export const enableSuspenseAvoidThisFallback = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
+1
@@ -16,6 +16,7 @@ export const enableProfilerTimer: boolean = __PROFILE__;
16 export const enableProfilerCommitHooks: boolean = __PROFILE__;
17 export const enableProfilerNestedUpdatePhase: boolean = __PROFILE__;
18 export const enableComponentPerformanceTrack: boolean = false;
19 +export const enablePerformanceIssueReporting: boolean = false;
20 export const enableUpdaterTracking: boolean = false;
21 export const enableLegacyCache: boolean = true;
22 export const enableAsyncIterableChildren: boolean = false;
packages/shared/forks/ReactFeatureFlags.www.js
+2
@@ -59,6 +59,8 @@ export const enableThrottledScheduling: boolean = false;
59
60 export const enableHydrationLaneScheduling: boolean = true;
61
62 +export const enablePerformanceIssueReporting: boolean = false;
63 +
64 // Logs additional User Timing API marks for use with an experimental profiling tool.
65 export const enableSchedulingProfiler: boolean =
66 __PROFILE__ && dynamicFeatureFlags.enableSchedulingProfiler;