Reputation: 5
I'm getting an error on the className of mapped elements. I believe TS is throwing the error because the map's children (MenuItem) don't have the className type. See the error below.
The mapped elements are part of the headlessui package. I think this is part of the reason I'm having trouble. I'm following this introduction to headlessui: https://headlessui.com/react/menu. This example is the third code sample on that page.
I tried to make the MenuItemProps interface to use on the .map function like this:
links.map((link): MenuButtonInterface => ()
How can I include the className type to the children of the .map function?
ERROR:
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>
)
}
Upvotes: 0
Views: 69
Reputation: 373
the issue that I can see is that you are not using the interface "MenuItemProps" that you have created in your component.
Since you are using Headlessui which already has it's own types, you can either use
<MenuItem as="div" className="block data-[focus]:bg-blue-500" {...({ key: link.href, children: <a href={link.href}>{link.label}</a>, } as MenuItemProps)} // Type assertion here />
// Custom component for handling props
const CustomMenuItem: React.FC < MenuItemProps > = ({
children,
className,
key,
}) => {
return ( <
MenuItem as = "div"
key = {
key
}
className = {
className
} > {
children
} <
/MenuItem>
);
};
// Use it in the code
{
links.map((link) => ( <
CustomMenuItem key = {
link.href
}
className = "block data-[focus]:bg-blue-500" >
<
a href = {
link.href
} > {
link.label
} < /a> <
/CustomMenuItem>
))
}
**Note: Answer below using
as Prop
works fine as well.**
Upvotes: 0
Reputation: 14
as
Prop Directly on MenuItemAccording to the docs you can use the as
prop directly in MenuItem
to render an a tag and it will allow you to pass the className
Code will look like this:
<MenuItem
key={link.href}
as="a"
href={link.href}
className="block data-[focus]:bg-blue-500"
{ link.label }
</MenuItem>
Hope this helps you.
Upvotes: 0