question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

`Listbox` does not trigger a form's `onChange` when using React Hook Form's `Controller` (but native `select` does)

See original GitHub issue

What package within Headless UI are you using?

@headlessui/react

What version of that package are you using?

v1.7.4

Reproduction URL

https://codesandbox.io/s/rhf-onchange-with-headlessuis-listbox-ce917d?file=/src/App.tsx

Describe your issue

I am not sure if this is a Headless UI issue, but this is my best guess.

Using the Listbox together with React Hook Form does not fire the form’s onChange.

Using a native select with the same setup does fire the onChange though, that’s why I created the issue here and not in the RHF repo.


In my reproduction you can see that the form is supposed to submit when the selection changes. Here, it logs to console, e.g.:

image

In the UI there are two selects: The first is via Listbox, the second is with a native select. When selecting an entry via Listbox, the value changes, but the form is not submitted (unexpected). When selecting an entry via the native select, the value changes and the form is submitted (as expected).

Code for reference, see CodeSandbox for full code:

function SelectNative({
  selected,
  onChange,
  name
}: {
  selected: string;
  onChange: (newSelected: string) => void;
  name: string;
}) {
  return (
    <select
      value={selected}
      onChange={(newSelected) => onChange(newSelected.currentTarget.value)}
      name={name}
    >
      {people.map((person) => (
        <option key={person.id} value={person.id}>
          {person.name}
        </option>
      ))}
    </select>
  );
}

function SelectWithListbox({
  selected,
  onChange,
  name
}: {
  selected: string;
  onChange: (newSelected: string) => void;
  name: string;
}) {
  return (
    <Listbox value={selected} onChange={onChange} name={name}>
      <Listbox.Button>
        {people.find((person) => person.id === selected)?.name}
      </Listbox.Button>
      <Listbox.Options>
        {people.map((person) => (
          <Listbox.Option key={person.id} value={person.id}>
            {person.name}
          </Listbox.Option>
        ))}
      </Listbox.Options>
    </Listbox>
  );
}

Issue Analytics

  • State:closed
  • Created 10 months ago
  • Reactions:3
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

3reactions
alex-pagecommented, Nov 12, 2022

I have the same problem with ComboBox

2reactions
adriandcommented, Nov 30, 2022

@alex-page the solution posted by @leapful works for the Combobox too.

const ref = useRef<HTMLSelectElement | null>(null);

  return (
    <>
      <select style={{ display: "none" }} ref={ref} />
      <Combobox
        as="div"
        value={selectedOption}
        onChange={(selected: any) => {
          setSelectedOption(selected);
          if (ref.current) {
            ref.current.dispatchEvent(new Event("change", { bubbles: true }));
          }
        }}
        name={props.name}
        id={props.id}
      >
Read more comments on GitHub >

github_iconTop Results From Across the Web

React-hook-form 'ignores' selects - Stack Overflow
The component Listbox (is an external controlled components) isn't a native HTML input. In this case, to deal with this component you should ......
Read more >
onChange not firing on controlled input with failed validation
Controlled inputs after failed validation don't fire onChange event. To Reproduce Steps to reproduce the behavior: Go to https://codesandbox.io/ ...
Read more >
Turn Anything Into A Form Field With React Hook Form ...
This is where Controller comes in! Often, the fields will use the same value and onChange prop names.
Read more >
API - React Select
A flexible and beautiful Select Input control for ReactJS with multiselect, autocomplete and ajax support.
Read more >
Select | Mantine
Select component allows user to pick one option from the given data , use this component when you need to create custom value...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found