0

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."

Zach philipp
  • 125
  • 6

0 Answers0