headlessui
headlessui copied to clipboard
Combobox v2 issue with dynamic fetched options in nextjs
What package within Headless UI are you using?
@headlessui/react
What version of that package are you using?
v2.0.3
What browser are you using?
Chrome
Reproduction URL
Describe your issue
After selecting an option and changing the input value the Input value resets back to the selected option. This is not how it was in the latest v1. This issue also seems only to occure in Nextjs. I could not reproduce it with the vite issue template.
- Type the letter "T" in inputfield and select the "Tailwind" option
- After selecting we want to search for something new, so we backspace 4 letters.
- This will trigger react query to run again and the input is reset to the selected value.
The excpected behavior is to not change the displayValue when changing the inputValue.
Here to say I'm experiencing the same thing
@lasseklovstad Following up here: I can temporarily get around this by setting the Combobox value to null
if the input value has changed. This obviously isn't great and impacts the UX negatively (e.g. blurring the field will not reset to the previously selected value by default), which means more code will need to be written by you to restore the ideal UX.
Here's some (simplified) code I'm using that's running in production now using @headlessui/react ^2.0.3
type Place = {
code: string; // can be empty string
type: string; // can be empty string
};
export type LocationPickerProps = {
/**
* Available options to populate the menu
*/
options: LocationResponse;
/**
* The selected value
*/
value: Place | null;
/**
* Callback whenever a new selection is made
*/
onChange(value: Place | null): void;
/**
* Callback whenever the search input value changes
*/
onSearch(search: string): void;
};
export function LocationPicker(props: LocationPickerProps) {
const {
onChange,
onSearch,
options,
value,
} = props;
const handleSearch = useMemo(
() => debounce((input: string) => onSearch(input)),
[onSearch],
);
return (
<Combobox
value={value}
onChange={(value) => onChange(value)}
as="div"
className="w-full"
by="code"
immediate
>
<Label className="flex w-full items-center gap-2.5 rounded-lg border border-grey-200 bg-grey-50 px-3 py-2.5 transition-all focus-within:border-grey-300 hover:border-grey-400">
<ComboboxInput
autoComplete="off"
placeholder="Choose location"
onChange={({ target }) => {
onChange(null); // <-- this fixes the bug in question
handleSearch(target.value);
}}
displayValue={(location: Place | null) => {
if (
location == null ||
(location.type === "" && location.code === "")
) {
return "";
}
const found = options.find(
(o) =>
o.code === location.code &&
o.granularLocationType === location.type,
);
return found?.title ?? "";
}}
className="flex-1 bg-transparent text-sm outline-none"
/>
</Label>
{/* ... */}
</Combobox>
);
}
This should be fixed by #3259, and will be available in the next release.
You can already try it using:
-
npm install @headlessui/react@insiders
.
Thanks @RobinMalfait 👍