-
Notifications
You must be signed in to change notification settings - Fork 47.5k
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
[DevTools] Show component names while highlighting renders #31577
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
packages/react-devtools-shared/src/devtools/views/Settings/SettingsContext.js
Outdated
Show resolved
Hide resolved
<div className={styles.Setting}> | ||
<label> | ||
<input | ||
type="checkbox" | ||
checked={showNamesWhenTracing} | ||
disabled={!traceUpdatesEnabled} | ||
onChange={({currentTarget}) => | ||
setShowNamesWhenTracing(currentTarget.checked) | ||
} | ||
/>{' '} | ||
Show component names while highlighting. | ||
</label> | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This probably should only be visible if "Highlight updates when components render."
is checked.
It is okay for now, I am thinking of moving this option to somewhere else, so it could be just a one-click toggle on / off.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left it visible with a disabled style for now to help with discoverability. I also have a separate branch where "Highlight updates when components render." is a toggle in the navbar next to the search, but I didn’t want to make this PR bigger, and I wasn’t sure which icons to use. Open to suggestions!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left it visible with a disabled style for now to help with discoverability.
Nice, this should be enough for now
I also have a separate branch where "Highlight updates when components render." is a toggle in the navbar next to the search
Feel free to open a separate PR for this, or the one on top of that
@@ -86,6 +96,11 @@ function traceUpdates(nodes: Set<HostInstance>): void { | |||
rect = measureNode(node); | |||
} | |||
|
|||
let displayName = agent.getComponentNameForHostInstance(node); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to gate it under showNames
? To save some milliseconds if this option is disabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. Do you think there’s a cleaner way to check if the component was optimized by the compiler? I saw the parseElementDisplayNameFromBackend
utility can return compiledWithForget
, but it needs thetype
. Not sure if I can get that from HostNode
since it’s typed as an object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if I can get that from HostNode since it’s typed as an object.
Here we operate with HostInstance
: HTMLElement
for Web (with react-dom
), and something completely different for Native, based on version and architecture of React Native.
You could leave it like this for now, maybe later we could add a new method to Agent
, which would map HostInstance
to DevToolsInstance
(this is what getComponentNameForHostInstance
is already doing), and then return if component is compiled or not, and maybe filter out HOC names.
const color = COLORS[colorIndex]; | ||
execute(rect, color, node); | ||
execute({...data, color, node}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to avoid unnecessary copying?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can convert it back to attributes if needed. I went with an object here because it felt more type-safe and flexible, but let me know what you think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can convert it back to attributes if needed. I went with an object here because it felt more type-safe and flexible, but let me know what you think.
This might become expensive, if the whole page re-renders? For each HTMLElement you will create a temporary copy here just for iteration purposes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay, I’ve been unwell. I replaced the spread operator with explicit object construction to avoid extra copies. Let me know if this solves the issue for you.
Love these improvements, thanks for opening this PR! Left some comments. I will try to get this supported for React Native, and I am also thinking about moving the checkbox to some other place, so this feature gets more visibility. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left 1 comment, please address it, linter and Flow issues.
Looks good overall, so once this is fixed, I can merge this
let displayName = this.showNames && agent.getComponentNameForHostInstance(node); | ||
if (displayName != null && displayName.startsWith('Forget(')) { | ||
displayName = '✨' + displayName.slice(7, -1); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a chance you might end up receiving TypeError
: calling displayName.startsWith(...)
if this.showNames
is false
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank for pointing that out. I’ve updated the code to avoid the potential TypeError by ensuring displayName
is only processed when showNames
is true.
I also revamped the display name parsing logic to make it more extensible. As part of this, I added a 🧠 icon for components wrapped in React.Memo
, and display names are now consistently unwrapped from HOCs for better clarity. Let me know if there’s anything else!
57fe23c
to
adaeb76
Compare
… type consistency
…ative - Introduced the `drawGroupedTraceUpdatesWithNames` event in `Agent` for emitting grouped trace updates. - This maintains backward compatibility while improving trace update organization for React Native. Note: This change only covers the JavaScript implementation; the native side still needs to be implemented.
2ddc311
to
bea90c4
Compare
Feature was added in #31577, lets enable it by default. Note: for gradual rollout with React Native, we will continue to emit different event, requires some changes on React Native side to support this. I have plans to make this feature to be accessible via browser context menu, which has really limited API. In order to minimize potential divergence, lets make this the default state for the feature.
List of changes in this release: * fix[DevTools]: fix HostComponent naming in filters for Native ([hoxyq](https://github.com/hoxyq) in [#32086](#32086)) * Fix copy functionality in Firefox ([V3RON](https://github.com/V3RON) in [#32077](#32077)) * chore[DevTools]: don't use batchedUpdate ([hoxyq](https://github.com/hoxyq) in [#32074](#32074)) * Prevent crash when starting consecutive profiling sessions ([V3RON](https://github.com/V3RON) in [#32066](#32066)) * fix[DevTools/Tree]: only scroll to item when panel is visible ([hoxyq](https://github.com/hoxyq) in [#32018](#32018)) * feat[Tree]: set initial scroll offset when inspected element index is set ([hoxyq](https://github.com/hoxyq) in [#31968](#31968)) * DevTools: merge element fields in TreeStateContext ([hoxyq](https://github.com/hoxyq) in [#31956](#31956)) * DevTools: fix initial host instance selection ([hoxyq](https://github.com/hoxyq) in [#31892](#31892)) * chore[DevTools/Tree]: don't pre-select root element and remove unused code ([hoxyq](https://github.com/hoxyq) in [#32015](#32015)) * chore[DevTools/TraceUpdates]: display names by default ([hoxyq](https://github.com/hoxyq) in [#32019](#32019)) * Add ViewTransitionComponent to Stacks and DevTools ([sebmarkbage](https://github.com/sebmarkbage) in [#32034](#32034)) * Add <ViewTransition> Component ([sebmarkbage](https://github.com/sebmarkbage) in [#31975](#31975)) * chore[react-devtools-shell]: disable warnings in dev server overlay ([hoxyq](https://github.com/hoxyq) in [#32005](#32005)) * DevTools: fork FastRefresh test for <18 versions of React ([hoxyq](https://github.com/hoxyq) in [#31893](#31893)) * Show component names while highlighting renders ([piotrski](https://github.com/piotrski) in [#31577](#31577)) * allow non-coercible objects in formatConsoleArgumentsToSingleString ([henryqdineen](https://github.com/henryqdineen) in [#31444](#31444)) * Remove enableRefAsProp feature flag ([kassens](https://github.com/kassens) in [#30346](#30346)) * [flow] Eliminate usage of more than 1-arg `React.AbstractComponent` in React codebase ([SamChou19815](https://github.com/SamChou19815) in [#31314](#31314)) * Audit try/finally around console patching ([sebmarkbage](https://github.com/sebmarkbage) in [#31286](#31286)) * tests[react-devtools]: added tests for Compiler integration ([hoxyq](https://github.com/hoxyq) in [#31241](#31241)) * Add Bridge types for Fusebox ([EdmondChuiHW](https://github.com/EdmondChuiHW) in [#31274](#31274))
Summary
This PR improves the Trace Updates feature by letting developers see component names directly on the update overlay. Before this change, the overlay only highlighted updated regions, leaving it unclear which components were involved. With this update, you can now match visual updates to their corresponding components, making it much easier to debug rendering performance.
New Feature: Show component names while highlighting
When the new "Show component names while highlighting" setting is enabled, the update overlay display the names of affected components above the rectangles, along with the update count. This gives immediate context about what’s rendering and why. The preference is stored in local storage and synced with the backend, so it’s remembered across sessions.
Improvements to Drawing Logic
The drawing logic has been updated to make the overlay sharper and easier to read. Overlay now respect device pixel ratios, so they look great on high-DPI screens. Outlines have also been made crisper, which makes it easier to spot exactly where updates are happening.
Note
Grouping Logic and Limitations
Updates are grouped by their screen position
(left, top coordinates)
to combine overlapping or nearby regions into a single group. Groups are sorted by the highest update count within each group, making the most frequently updated components stand out.Overlapping labels may still occur when multiple updates involve components that overlap but are not in the exact same position. This is intentional, as the logic aims to maintain a straightforward mapping between update regions and component names without introducing unnecessary complexity.
Testing
This PR also adds tests for the new
groupAndSortNodes
utility, which handles the logic for grouping and sorting updates. The tests ensure the behavior is reliable across different scenarios.Before & After
Before.mov
After.with.labels.mov