Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 2, 2026

useDeferredValue requires memoization to prevent synchronous re-renders. Without React.memo, the deferred value provides no performance benefit—React still re-renders the entire list while typing.

Changes

Created FilteredActionListItems memoized component

  • Extracted list rendering logic (grouped and ungrouped) into React.memo-wrapped component
  • Receives deferredItems and stable props (getItemListForEachGroup already has empty deps)
  • Enables React to skip re-renders when deferred value hasn't updated yet

Refactored component structure

  • Moved MappedActionListItem before FilteredActionList for availability
  • Updated getBodyContent() to render memoized component
  • Immediate items still used for Enter key handling (unchanged)

Pattern follows Autocomplete's approach with useMemo and deferredInputValue.

Changelog

Changed

  • FilteredActionList now uses memoized list rendering for better typing performance with large item lists

Rollout strategy

  • Patch release
  • Minor release
  • Major release; if selected, include a written rollout or migration plan
  • None; if selected, include a brief description as to why

Testing & Reviewing

Test typing performance in FilteredActionList stories with large item lists (100+ items). Input should remain responsive while list updates with deferred priority.

Merge checklist

Original prompt

Problem

The current implementation in PR #7411 adds useDeferredValue(items) to FilteredActionList, but this alone doesn't provide the expected performance benefit. useDeferredValue only helps when the deferred value is used by a memoized component (via React.memo) or memoized computation (via useMemo). Without memoization, React still re-renders everything synchronously.

The Autocomplete component's implementation works because it pairs useDeferredValue with useMemo for the filtered items (see AutocompleteMenu.tsx lines 229-235).

Solution

Create a memoized child component (React.memo) to wrap the list rendering logic in FilteredActionList.tsx. This will allow React to skip re-rendering the list when deferredItems hasn't updated yet, keeping the input responsive.

Implementation Details

  1. Extract the list rendering logic (both grouped and ungrouped items) into a new memoized component called FilteredActionListItems
  2. Use React.memo to wrap this component
  3. Pass deferredItems to this memoized component
  4. Ensure all props passed to the memoized component are stable (the existing getItemListForEachGroup with empty dependency array is already good)
  5. Keep using immediate items for user interactions (Enter key handling) as the PR currently does

Files to Modify

  • packages/react/src/FilteredActionList/FilteredActionList.tsx

Reference

The pattern should work similar to how Autocomplete uses useMemo with deferredInputValue:

// From AutocompleteMenu.tsx
const sortedAndFilteredItemsToRender = useMemo(
  () =>
    selectableItems
      .filter(filterFn ? filterFn : getDefaultItemFilter(deferredInputValue))
      .sort((a, b) => itemSortOrderData[a.id] - itemSortOrderData[b.id]),
  [selectableItems, itemSortOrderData, filterFn, deferredInputValue],
)

But instead of useMemo for JSX, use a React.memo wrapped component for cleaner separation and more robust memoization.

This pull request was created from Copilot chat.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@changeset-bot
Copy link

changeset-bot bot commented Jan 2, 2026

⚠️ No Changeset found

Latest commit: 829a3d0

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copilot AI changed the title [WIP] Add memoized component for list rendering in FilteredActionList Add React.memo to FilteredActionList for effective useDeferredValue performance Jan 2, 2026
Copilot AI requested a review from mattcosta7 January 2, 2026 23:32
@github-actions github-actions bot added the integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm label Jan 2, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Jan 2, 2026

👋 Hi, this pull request contains changes to the source code that github/github-ui depends on. If you are GitHub staff, test these changes with github/github-ui using the integration workflow. Or, apply the integration-tests: skipped manually label to skip these checks.

@mattcosta7 mattcosta7 marked this pull request as ready for review January 2, 2026 23:54
@mattcosta7 mattcosta7 requested a review from a team as a code owner January 2, 2026 23:54
@mattcosta7 mattcosta7 merged commit b93b609 into copilot/optimize-filtered-action-list Jan 2, 2026
47 of 48 checks passed
@mattcosta7 mattcosta7 deleted the copilot/create-filtered-action-list-items branch January 2, 2026 23:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants