I am trying to use the code example below in Next.js 15 (TypeScript), but getting the error on the line onChange={setSelectedPerson}
and would like to know how to specify the types on passing:
Type error: Type 'Dispatch<SetStateAction<{ id: number; name: string; }>>' is not assignable to type '(value: NoInfer<{ id: number; name: string; }> | null) => void'.
Types of parameters 'value' and 'value' are incompatible.
Type 'NoInfer<{ id: number; name: string; }> | null' is not assignable to type 'SetStateAction<{ id: number; name: string; }>'.
Type 'null' is not assignable to type 'SetStateAction<{ id: number; name: string; }>'.
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
const people = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
const [selectedPerson, setSelectedPerson] = useState(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput
aria-label="Assignee"
displayValue={(person) => person?.name}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
Here’s how you can fix this issue:
import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react'
import { useState } from 'react'
// Define the type for people
interface Person {
id: number
name: string
}
const people: Person[] = [
{ id: 1, name: 'Durward Reynolds' },
{ id: 2, name: 'Kenton Towne' },
{ id: 3, name: 'Therese Wunsch' },
{ id: 4, name: 'Benedict Kessler' },
{ id: 5, name: 'Katelyn Rohan' },
]
function Example() {
// Allow selectedPerson to be null as well
const [selectedPerson, setSelectedPerson] = useState<Person | null>(people[0])
const [query, setQuery] = useState('')
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox value={selectedPerson} onChange={setSelectedPerson} onClose={() => setQuery('')}>
<ComboboxInput
aria-label="Assignee"
displayValue={(person: Person | null) => person?.name || ''}
onChange={(event) => setQuery(event.target.value)}
/>
<ComboboxOptions anchor="bottom" className="border empty:invisible">
{filteredPeople.map((person) => (
<ComboboxOption key={person.id} value={person} className="data-[focus]:bg-blue-100">
{person.name}
</ComboboxOption>
))}
</ComboboxOptions>
</Combobox>
)
}
export default Example