Skip to content

Conversation

@emily8rown
Copy link
Contributor

@emily8rown emily8rown commented Nov 27, 2025

Summary

Add keyboard shortcuts (Cmd/Ctrl + Left/Right arrow keys) to navigate between commits in the Profiler's snapshot view.

Moved filteredCommitIndices management and commit navigation logic (selectNextCommitIndex, selectPrevCommitIndex) from SnapshotSelector into useCommitFilteringAndNavigation used by ProfilerContext to enable keyboard shortcuts from the top-level Profiler component.

How did you test this change?

  • New tests in ProfilerContext-tests
  • Built and tested in browser: yarn build:<browser name>
  • Ran tests: yarn run test:<browser name>
  • Manually verified Left/Right arrow navigation cycles through commits
  • Verified navigation respects commit duration filter

Chrome:

Screen.Recording.2025-11-27.at.18.19.45.mov

Edge with duration filter:

Screen.Recording.2025-11-28.at.12.23.23.mov

firefox mixing hotkey with clicking arrow buttons:

Screen.Recording.2025-11-28.at.12.34.07.mov

@meta-cla meta-cla bot added the CLA Signed label Nov 27, 2025
@emily8rown emily8rown marked this pull request as ready for review November 28, 2025 14:22
@emily8rown emily8rown requested a review from hoxyq November 28, 2025 14:23
selectedCommitIndex !== null
) {
// Left/Right to navigate commits
if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably check for Cmd key as well. I think we should keep just arrow navigations for changes between nodes in tree view (outside of the scope for this PR), and Cmd + ->, Cmd + <- for navigation between commits. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it's nicer to have them unique but the arrow navigation for the tree view nodes only works when one has just been selected and when that has happened even having them as different shortcuts you can't use a shortcut to navigate between commits. I'm not convinced how much the tab navigation one will be used if your mouse has already selected a tab in the area there just before, and therefore it could be nicer to leave the shortcut as arrow key for simplicity

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it would confuse people they are switching tabs when they expect to switch commits if they don't realise they need to select it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure I am following. We don't have keyboard navigation for the flamegraph in Profiler tree, right? But if we would add one, it would probably be done by using only arrow keys.

If so, then it would conflict with the navigation between commits. That's my current thinking, what is the alternative?


// Profile and record multiple commits
await utils.actAsync(() => store.profilerStore.startProfiling());
await utils.actAsync(() => legacyRender(<Parent />, container)); // Commit 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For new tests, we should try to use ReactDOMClient.createRoot and root.render(), unless we are testing against React with version prior to 18.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be a test for both?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, because this feature is independent from the version of React we are debugging.

Comment on lines 312 to 324
const numFilteredCommits = filteredCommitIndices.length;
if (selectedFilteredCommitIndex === null && numFilteredCommits > 0) {
selectCommitIndex(filteredCommitIndices[0]);
} else if (
selectedFilteredCommitIndex !== null &&
selectedFilteredCommitIndex >= numFilteredCommits
) {
selectCommitIndex(
numFilteredCommits === 0
? null
: filteredCommitIndices[numFilteredCommits - 1],
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this to setMinCommitDuration? So that these updates get batched and to avoid cascading update here, even if it could be cheap

document.body.removeChild(profilerContainer);
});

// @reactVersion >= 18
Copy link
Contributor

@hoxyq hoxyq Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to specify this. If you remove the pragma, it will only run the test against React from source.

[setRootID, selectFiber],
);

// why am i doing this instead of use effect
Copy link
Contributor

@hoxyq hoxyq Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In most of the cases, passive effects (useEffect(...)) run after the new UI is painted on the screen. If this logic would be inside an effect, then the browser could paint a frame with a UI derived from a stale state. This is quite common root cause of UI thrashing problems.

Having this logic inside a render function causes a cascading re-render, but it eliminates the possibility of showing a stale UI that will be changed by the next frame.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants