Skip to content

[devtools]: Prevent false positive render detection in profiler (#33423, #19732) #33964

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 41 additions & 6 deletions packages/react-devtools-shared/src/backend/fiber/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2813,7 +2813,19 @@ export function attach(
pushOperation(convertedTreeBaseDuration);
}

if (prevFiber == null || didFiberRender(prevFiber, fiber)) {
// Prevent false positive render detection when identical Fiber objects
// are nested under HostComponents (like div) that get filtered out by DevTools.
// This addresses cases where a parent HostComponent re-renders but its child
// components (like function components) remain referentially identical and
// should not be reported as having re-rendered in profiler data collection.
if (
prevFiber == null ||
(!(
prevFiber === fiber &&
fiber.return != null &&
(fiber.return.tag === HostComponent || fiber.return.tag === HostSingleton)
) && didFiberRender(prevFiber, fiber))
) {
if (actualDuration != null) {
// The actual duration reported by React includes time spent working on children.
// This is useful information, but it's also useful to be able to exclude child durations.
Expand Down Expand Up @@ -3312,11 +3324,25 @@ export function attach(
elementType === ElementTypeMemo ||
elementType === ElementTypeForwardRef
) {
// Otherwise if this is a traced ancestor, flag for the nearest host descendant(s).
traceNearestHostComponentUpdate = didFiberRender(
prevFiber,
nextFiber,
);
// Prevent false positive render highlighting when identical Fiber objects
// are nested under HostComponents that get filtered out by DevTools.
// When a HostComponent (like div) re-renders but its child components
// remain referentially identical (prevFiber === nextFiber), those children
// should not be highlighted as having re-rendered since they were effectively
// skipped during React's reconciliation process.
if (
prevFiber === nextFiber &&
nextFiber.return != null &&
(nextFiber.return.tag === HostComponent || nextFiber.return.tag === HostSingleton)
) {
traceNearestHostComponentUpdate = false; // No actual render for this component
} else {
// Otherwise if this is a traced ancestor, flag for the nearest host descendant(s).
traceNearestHostComponentUpdate = didFiberRender(
prevFiber,
nextFiber,
);
}
}
}
}
Expand All @@ -3330,6 +3356,15 @@ export function attach(
if (
mostRecentlyInspectedElement !== null &&
mostRecentlyInspectedElement.id === fiberInstance.id &&
// Prevent unnecessary inspector cache invalidation when identical Fiber objects
// are nested under HostComponents that get filtered out by DevTools.
// When a component hasn't actually re-rendered (same Fiber reference under a HostComponent),
// we should preserve the cached inspection data to avoid unnecessary re-computation.
!(
prevFiber === nextFiber &&
nextFiber.return != null &&
(nextFiber.return.tag === HostComponent || nextFiber.return.tag === HostSingleton)
) &&
didFiberRender(prevFiber, nextFiber)
) {
// If this Fiber has updated, clear cached inspected data.
Expand Down