I am using HeadlessUI to abstract a listbox component. I can't seem to understand how I pass setState or a state changing function. Here is my listBox component
import { ChevronUpDownIcon, XMarkIcon } from "@heroicons/react/20/solid";
import { Listbox, Transition } from "@headlessui/react";
import { Fragment } from "react";
import { useState } from "react";
const ControllerListBox = ({ placeHolder, apps, selected, setSelected }) => {
// const [selected, setSelected] = useState(value);
return (
<Listbox value={selected} onChange={setSelected}>
<div className="relative py-2 mt-1 ">
<span
className={`text-lg tracking-wide absolute -translate-y-4 ${
selected != ""
? "text-blue-300 scale-1 transition duration-[350ms]"
: "text-gray-400 scale-0 transition duration-[350ms]"
}`}
>
{placeHolder}
</span>
<Listbox.Button
className={`relative py-2 pr-10 text-left cursor-default w-60 border-b-4 focus:outline-none ${
selected != "" ? "border-b-blue-300" : "border-b-gray-400"
}`}
>
<span
className={`block truncate tracking-wide text-gray-400 text-lg ${
selected ? "text-white" : "text-gray-400"
}`}
>
{selected ? selected.name : placeHolder}
</span>
<span
className={`absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none ${
selected != "" ? "hidden" : ""
}`}
>
<ChevronUpDownIcon
className="w-5 h-5 text-gray-400"
aria-hidden="true"
/>
</span>
<span
className={`absolute inset-y-0 right-0 flex items-center pr-2 ${
selected != "" ? "" : "hidden"
}`}
onClick={() => {
setSelected("");
}}
>
<XMarkIcon className="w-5 h-5 text-gray-400" aria-hidden="true" />
</span>
</Listbox.Button>
<Transition
as={Fragment}
leave="transition ease-in duration-150"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div style={{ position: "relative", zIndex: 20 }}>
<Listbox.Options className="absolute py-1 mt-1 overflow-auto text-base rounded-md shadow-lg bg-white/90 w-60 h-44 z-100 max-h-60 ring-1 ring-black ring-opacity-5 focus:outline-none scrollable">
{apps.map((app, appIdx) => (
<Listbox.Option
key={appIdx}
className={({ active }) =>
`relative cursor-default select-none py-2 pl-2 pr-4 ${
active ? "bg-white text-gray-900" : "text-gray-900"
}`
}
value={app}
>
{({ selected }) => (
<>
<span
className={`block truncate ${
selected
? "text- tracking-wide"
: "text-md tracking-wide"
}`}
>
{app.name}
</span>
{/* {selected ? (
<span className="absolute inset-y-0 left-0 flex items-center pl-3 text-gray-900 ">
<CheckIcon
className="w-5 h-5"
aria-hidden="true"
/>
</span>
) : null} */}
</>
)}
</Listbox.Option>
))}
</Listbox.Options>
</div>
</Transition>
</div>
</Listbox>
);
};
export default ControllerListBox;
here is my reference in another file
export default function Home() {
const [control, setControl] = useState("");
const apps = [
{ name: "Yeah", class: "ues" },
{ name: "No", class: "ues" },
];
const [selected, setSelected] = useState("");
const handleSelectChange = (value) => {
setSelected(value);
};
return (
<>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className="m-auto h-screen bg-gray-900 flex justify-center items-center flex-col space-y-8">
<ControllerListBox
placeHolder={"User Type"}
apps={apps}
selected={selected}
setSelected={handleSelectChange}
/>
</main>
</>
);
}
When I try to click on an option i get the runtime error "Error: Objects are not valid as a React child (found: object with keys {name, class}). If you meant to render a collection of children, use an array instead."