fix: Improve ListBox perf caused by excessive re-rendering #8010
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I use a
Select
(ListBox
) to display a list of countries in an address component for my project. There are about ~200 countries, few enough that virtualization isn't necessary. However, there is a noticeable delay when hovering the mouse over countries or changing the selected country using the keyboard.This delay stems from the
ListBox
re-rendering everyListBoxItem
whenever the hovered item changes:94490600-503618712-Recording_2025-03-29_192152.mp4
In the lower right corner, you can see the FPS drop sharply.
I tracked down the source to several un-memoized objects that get re-created every render. As React diffs props by reference, this causes a full render on all
ListBoxItem
s. I addeduseMemo(..)
s were appropriate, and now the performance is much smoother - only two re-renders occur (the newly and previously hovered items):295701505-74604607-Recording_2025-03-29_192319.mp4
✅ Pull Request Checklist:
📝 Test Instructions:
I used the
React Aria Components > Select Many
story without any modifications to demonstrate the issue/fix:I used the React Scan extension to identify the un-memoized objects - I had to force the
Popover
within the Select Many example open withisOpen={true}
so I could select it with React Scan.🧢 Your Project:
RSP