如何为映射元素声明类型?解决HeadlessUI MenuItem className报错
问题描述
使用HeadlessUI的MenuItem组件做数组映射时,给MenuItem添加className属性触发TypeScript报错,提示该属性不存在于组件的类型定义中。尝试自定义MenuItemProps接口未解决问题。
报错信息
Type '{ children: Element; key: string; className: string; }' is not assignable to type 'IntrinsicAttributes & CleanProps<ExoticComponent<{ children?: ReactNode; }>, "disabled" | ItemPropsWeControl> & OurProps<...> & { ...; } & { ...; }'. Property 'className' does not exist on type 'IntrinsicAttributes & CleanProps<ExoticComponent<{ children?: ReactNode; }>, "disabled" | ItemPropsWeControl> & OurProps<...> & { ...; } & { ...; }'.ts(2322)
原代码
import React, { ReactNode } from 'react' import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react' const links = [ {href: '/home', label: 'Home'}, {href: '/Test', label: 'Test'}, {href: '/settings', label: 'Settings'} ] interface MenuItemProps{ children: any className?: any key: any } export const MyComponent = () => { return( <Menu> <MenuButton className='data-[active]:bg-blue-500'></MenuButton> <MenuItems anchor='bottom'> {links.map((link) => ( <MenuItem key={link.href} className='block data-[focus]:bg-blue-500'> <a href={link.href}>{link.label}</a> </MenuItem> ))} </MenuItems> </Menu> ) }
解决方法
HeadlessUI的MenuItem组件本身不支持直接传入className属性,正确的做法是将样式应用到它内部的元素上,或通过render prop模式利用组件提供的状态动态设置样式:
方法1:将 className 转移到内部元素
直接把样式加到MenuItem包裹的<a>标签上,同时可保留HeadlessUI的状态驱动data属性(如data-[focus]):
export const MyComponent = () => { return( <Menu> <MenuButton className='data-[active]:bg-blue-500'></MenuButton> <MenuItems anchor='bottom'> {links.map((link) => ( <MenuItem key={link.href}> <a href={link.href} className='block data-[focus]:bg-blue-500' > {link.label} </a> </MenuItem> ))} </MenuItems> </Menu> ) }
方法2:使用 render prop 获取状态动态设样式
通过MenuItem的render prop形式拿到组件的状态(如active),自定义样式逻辑:
export const MyComponent = () => { return( <Menu> <MenuButton className='data-[active]:bg-blue-500'></MenuButton> <MenuItems anchor='bottom'> {links.map((link) => ( <MenuItem key={link.href} as={React.Fragment}> {({ active }) => ( <a href={link.href} className={`block ${active ? 'bg-blue-500' : ''}`} > {link.label} </a> )} </MenuItem> ))} </MenuItems> </Menu> ) }
为什么自定义接口没用?
你自定义的MenuItemProps并没有关联到HeadlessUI提供的MenuItem组件类型上,组件的props类型由库本身定义,自定义接口无法覆盖或扩展它的类型约束。
内容的提问来源于stack exchange,提问作者giveearholdtongue
相关产品推荐
相关产品推荐

