I tried to use a Navbar from the Tailwind component library, but there's something wrong with the way I'm using Headless UI. I'm following https://headlessui.com/react/disclosure and I can't figure out how to implement the render prop example. I have a Next.js project and two main files, page.tsx and Example.tsx
//src/app/page.tsx
import React from "react";
import Example from "@/components/ui/Example";
export default function Home() {
return (
<main>
<Example />
</main>
);
}
//src/ui/Example.tsx
import { Disclosure, DisclosureButton, DisclosurePanel } from "@headlessui/react";
import { ChevronDownIcon } from "@heroicons/react/20/solid";
import clsx from "clsx";
export default function Example() {
return (
<Disclosure>
{({ open }) => (
<>
<DisclosureButton className="flex items-center gap-2">
Do you offer technical support?
<ChevronDownIcon className={clsx("w-5", open && "rotate-180")} />
</DisclosureButton>
<DisclosurePanel>No</DisclosurePanel>
</>
)}
</Disclosure>
);
}
I am getting:
Error: Functions are not valid as a child of Client Components. This may happen if you return children instead of from render. Or maybe you meant to call this function rather than return it. <... children={function children}>
The problem seems to be the {({open}) => ...}
function. I need to turn it into a valid component, but I don't know how.
In NextJS, all components are Server Components by default.
Disclosure needs to be a Client component because it has to be interactive (show/hide) and may be using some hooks (which is only available in client components)
// add "use client" directive
"use client"
import { Disclosure, DisclosureButton, DisclosurePanel } from "@headlessui/react";
import { ChevronDownIcon } from "@heroicons/react/20/solid";
import clsx from "clsx";
export default function Example() {
return (
<Disclosure>
{({ open }) => (
<>
<DisclosureButton className="flex items-center gap-2">
Do you offer technical support?
<ChevronDownIcon className={clsx("w-5", open && "rotate-180")} />
</DisclosureButton>
<DisclosurePanel>No</DisclosurePanel>
</>
)}
</Disclosure>
);
}