diff --git a/packages/react-reconciler/src/ReactFiberPerformanceTrack.js b/packages/react-reconciler/src/ReactFiberPerformanceTrack.js index 5f94bd35e0..f926bd6085 100644 --- a/packages/react-reconciler/src/ReactFiberPerformanceTrack.js +++ b/packages/react-reconciler/src/ReactFiberPerformanceTrack.js @@ -36,6 +36,7 @@ import { import { enableProfilerTimer, enableGestureTransition, + enablePerformanceIssueReporting, } from 'shared/ReactFeatureFlags'; const supportsUserTiming = @@ -203,6 +204,15 @@ const reusableComponentOptions: PerformanceMeasureOptions = { const reusableChangedPropsEntry = ['Changed Props', '']; +const reusableCascadingUpdateIssue = { + name: 'React: Cascading Update', + severity: 'warning', + description: + 'A cascading update is an update that is triggered during an ongoing render. This can lead to performance issues.', + learnMoreUrl: + 'https://react.dev/reference/dev-tools/react-performance-tracks#cascading-updates', +}; + const DEEP_EQUALITY_WARNING = 'This component received deeply equal props. It might benefit from useMemo or the React Compiler in its owner.'; @@ -761,6 +771,11 @@ export function logBlockingStart( }, }, }; + if (enablePerformanceIssueReporting && isSpawnedUpdate) { + // $FlowFixMe[prop-missing] - detail is untyped + measureOptions.detail.devtools.performanceIssue = + reusableCascadingUpdateIssue; + } if (debugTask) { debugTask.run( diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index 68410612b5..6d45a30718 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -232,6 +232,11 @@ export const enableProfilerTimer = __PROFILE__; // All calls should also be gated on enableProfilerTimer. export const enableComponentPerformanceTrack: boolean = true; +// Enables annotating of React performance track events with `performanceIssue` +// metadata, to more prominently highlight performance issues to users +// (initially, an experimental feature in React Native). +export const enablePerformanceIssueReporting: boolean = false; + // Adds user timing marks for e.g. state updates, suspense, and work loop stuff, // for an experimental timeline tool. export const enableSchedulingProfiler: boolean = diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js index 8a2e7921bd..dbf92a2190 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js @@ -83,6 +83,8 @@ export const enableDefaultTransitionIndicator: boolean = true; export const ownerStackLimit = 1e4; export const enableComponentPerformanceTrack: boolean = __PROFILE__ && dynamicFlags.enableComponentPerformanceTrack; +export const enablePerformanceIssueReporting: boolean = + enableComponentPerformanceTrack; // Flow magic to verify the exports of this file match the original version. ((((null: any): ExportsType): FeatureFlagsType): ExportsType); diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js index e9de8e6b4a..c509dbce69 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-oss.js +++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js @@ -42,6 +42,7 @@ export const enablePostpone: boolean = false; export const enableReactTestRendererWarning: boolean = false; export const enableRetryLaneExpiration: boolean = false; export const enableComponentPerformanceTrack: boolean = true; +export const enablePerformanceIssueReporting: boolean = false; export const enableSchedulingProfiler: boolean = !enableComponentPerformanceTrack && __PROFILE__; export const enableScopeAPI: boolean = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js index 57de815d9c..5ae58dab14 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js @@ -16,6 +16,7 @@ export const enableProfilerTimer: boolean = __PROFILE__; export const enableProfilerCommitHooks: boolean = __PROFILE__; export const enableProfilerNestedUpdatePhase: boolean = __PROFILE__; export const enableComponentPerformanceTrack: boolean = true; +export const enablePerformanceIssueReporting: boolean = false; export const enableUpdaterTracking: boolean = false; export const enableLegacyCache: boolean = __EXPERIMENTAL__; export const enableAsyncIterableChildren: boolean = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js index eb56da603d..91803ab38a 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js @@ -41,6 +41,7 @@ export const enableReactTestRendererWarning = false; export const enableRetryLaneExpiration = false; export const enableSchedulingProfiler = __PROFILE__; export const enableComponentPerformanceTrack = false; +export const enablePerformanceIssueReporting = false; export const enableScopeAPI = false; export const enableEagerAlternateStateNodeCleanup = true; export const enableSuspenseAvoidThisFallback = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js index 90e24f264d..dd98285107 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js @@ -16,6 +16,7 @@ export const enableProfilerTimer: boolean = __PROFILE__; export const enableProfilerCommitHooks: boolean = __PROFILE__; export const enableProfilerNestedUpdatePhase: boolean = __PROFILE__; export const enableComponentPerformanceTrack: boolean = false; +export const enablePerformanceIssueReporting: boolean = false; export const enableUpdaterTracking: boolean = false; export const enableLegacyCache: boolean = true; export const enableAsyncIterableChildren: boolean = false; diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js index 9d8be29c65..542d72c2f6 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -59,6 +59,8 @@ export const enableThrottledScheduling: boolean = false; export const enableHydrationLaneScheduling: boolean = true; +export const enablePerformanceIssueReporting: boolean = false; + // Logs additional User Timing API marks for use with an experimental profiling tool. export const enableSchedulingProfiler: boolean = __PROFILE__ && dynamicFeatureFlags.enableSchedulingProfiler;