Listbox render props clearing when parent component state changes #854
-
I feel like I could be misunderstanding something very basic, but I can't seem to find a solution to this anywhere. When I create a component that contains a Headless UI listbox and include it in a parent component, if a hook causes state to change in the parent, the For example, for the following component function ListboxComponent(items, onChange, value) {
return (
<Listbox
value={value}
onChange={onChange}
>
<Listbox.Button>{value.name}</Listbox.Button>
<Listbox.Options>
{items.map((item) => (
<Listbox.Option key={item.id} value={item} as={Fragment}>
{({ selected }) => (
<li className="flex justify-between">
<span className={`font-base p-1`}>{item.name}</span>
{selected ? <CheckIcon className="h-5 w-5" /> : null}
</li>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Listbox>
)
} If I import this component into another: import ListboxComponent from '../somewhere'
function ParentComponent() {
const items = [
{
id: 1,
name: 'one'
},
{
id: 2,
name: 'two'
}
]
const test = useDelay() // a custom hook that sets "test" to true after 5 seconds
const [selected, setSelected] = useState(items[0])
return (
<>
<div>Some other content to render</div>
<ListboxComponent items={items} onChange={setSelected} value={selected} />
</>
)
}
export default ParentComponent The listbox will correctly render and check the first option. However, after 5 seconds, the Any idea on what's causing the render prop to clear when any arbitrary state in the parent changes, even when that state doesn't necessarily affect any rendering in the parent component? I'm not super well-versed in react, so this might be me simply not understanding something basic. Thanks! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Hey! Thank you for your question! The issue is that your You can apply a few fixes here:
With "stable" I mean the reference: 1 === 1 // true
{ id: 1 } === { id: 1 } // false |
Beta Was this translation helpful? Give feedback.
Hey! Thank you for your question!
Much appreciated! 🙏
The issue is that your
const items
inside theParentComponent
will be re-created every render, therefore all the objects inside the array will also be recreated every render and thereforeitems.includes(knownItemInTheComponent)
will always befalse
.You can apply a few fixes here:
items
array is stable over multiple renders. You can use auseState
oruseRef
item.id
as the value instead of theitem
itself. Because yourid
is a primitive and therefore will be stable over time.With "stable" I mean the reference: