Skip to content

Combobox: typing gets quadratically slower with the number of rendered options (1000 options ≈ 3.5 s per keystroke) #3898

Open

Description

@corneliusroemer

What package within Headless UI are you using?

@headlessui/react

What version of that package are you using?

v2.2.10 (React 19.3.0)

What browser are you using?

Chrome for Testing 153 (headless), arm64 Linux

Reproduction URL

https://github.com/corneliusroemer-agent/headlessui-combobox-many-options

Describe your issue

A non-virtual Combobox gets slow to type into as the number of rendered options grows: doubling the options makes a keystroke about 5× slower. Listbox with the same options stays fast.

Steps:

git clone https://github.com/corneliusroemer-agent/headlessui-combobox-many-options
cd headlessui-combobox-many-options
npm install && npm run build && npm run preview
  1. Run above steps
  2. Open http://localhost:4173/?n=1000
  3. Click the input and type 1

The page shows the time from the input event to the next animation frame. ?c=listbox renders the same options in a static Listbox filtered by a plain <input> (?static=1 renders the Combobox options with static too, and is just as slow), and ?c=plain renders them as plain <li> elements.

Expected: updating 1000 options takes about as long as in Listbox (tens of ms), growing linearly with the option count.

Typing 1, median of 5 runs:

options Combobox Combobox, order={index} Listbox plain <li>
250 131 ms 120 ms 15 ms 4 ms
500 687 ms 606 ms 19 ms 6 ms
1000 3,481 ms 2,710 ms 32 ms 11 ms

Typing 1 at n=1000 unmounts 729 options and mounts 729 new ones, and each ComboboxOption dispatches its own RegisterOption/UnregisterOption. In a CPU profile of that keystroke, about 55% of the time is shallowEqual under Machine.send, run for each of the three store subscriptions of every mounted option on every dispatch, and about 20% is compareDocumentPosition from re-sorting the option list. order={index} (?order=1) removes the sort but not the rest. Listbox batches registration into one dispatch; #3697 left the same change for Combobox to a follow-up.

Related:

  • Improve Combobox component performance #3697, "Improve Combobox component performance", merged 2025-04-17 and shipped in 2.2.2. Its description says batching Combobox option registration, as Listbox and Menu already do, was left for a follow-up PR. I couldn't find that follow-up PR.
  • Performance issues with ComboBox for big lists(100+ data) #2984, "Performance issues with ComboBox for big lists(100+ data)", February 2024, 4 comments, no maintainer answer. Mostly about the Vue package and predates the 2.2.2 rewrite, so it's related rather than the same bug.

Activity

  1. tevinch commented on Oct 2, 2026

    @tevinch

    I opened #3899 with batched option registration and synchronous flushes before selection and navigation. It keeps the non-virtual rendering path and includes focus/Tab, StrictMode and virtual-transition regressions.

    The pinned source build and install instructions are available if you'd like to try it in the lineage search. The full local suite passes (2,052 tests), and software-operated Chrome checks completed repeated selection with 1,000 options. It is still under review; I haven't verified timing on your Linux setup.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions