我尝试使用 Tailwind 组件库中的导航栏,但我使用 Headless UI 的方式有问题。我正在关注 https://headlessui.com/react/disclosure,但我不知道如何实现 render prop 示例。我有一个 Next.js 项目和两个主文件,page.tsx 和 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>
);
}
我得到:
错误:函数作为客户端组件的子组件无效。如果您返回子级而不是从渲染返回,则可能会发生这种情况。或者也许您打算调用此函数而不是返回它。 <... children={function children}>
问题似乎出在
{({open}) => ...}
函数上。我需要将它变成一个有效的组件,但我不知道如何做。
在 NextJS 中,所有组件默认都是 服务器组件。
Disclosure需要是客户端组件,因为它必须是交互式的(显示/隐藏)并且可能使用一些钩子(仅在客户端组件中可用)
// 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>
);
}