[英]React and Typescript dynamic component from config
我正在尝试使用 reactjs 和 typescript 构建动态菜单系统。
我的配置如下所示:
import {TableIcon} from "@heroicons/react/solid";
type route = {
icon: React.ReactNode,
path: string,
title: string,
}
export const navRoutes = () : route[] => {
return [
{
icon: TableIcon,
path: '/',
title: 'Home'
},
]
}
在我的导航组件中,我正在做
{navRoutes().map((item) => (
<a key={item.title} href={item.path}>
<item.icon /> // also tried {item.icon}
{item.title}
</a>
))}
我收到TS2604: JSX element type 'item.icon' does not have any construct or call signatures.
在没有按预期工作的 typescript 的情况下,我做了类似的事情——谁能告诉我我做错了什么?
React.ReactNode
是渲染组件的类型。 例如:
const a: React.ReactNode = <TableIcon />
如果你想传入一些渲染的JSX,那就是你会使用的。 但听起来你想传入一个没有道具的功能组件,然后将其渲染。
React.FC
是没有 props 的 react 功能组件的通用类型。 这可能就是你想要的类型。
type route = {
icon: React.FC,
path: string,
title: string,
}
React.ReactNode
类型描述了调用 JSX 组件而不是组件本身的返回值。 您可以:
1)传递一个React.ReactNode
:
type route = {
icon: React.ReactNode;
path: string;
title: string;
};
export const navRoutes = (): route[] => {
return [
{
icon: <TableIcon />,
path: "/",
title: "Home"
}
];
};
{navRoutes().map((item) => (
<a key={item.title} href={item.path}>
{item.icon}
{item.title}
</a>
))}
<item.icon/>
似乎有效? 但为了安全起见,我会使用它。type route = {
icon: React.ComponentType;
path: string;
title: string;
};
export const navRoutes = (): route[] => {
return [
{
icon: TableIcon,
path: "/",
title: "Home"
}
];
};
{navRoutes().map(({title, path, icon: Icon}) => (
<a key={title} href={path}>
<Icon/>
{title}
</a>
))}
默认情况下React.ComponentType
不接受任何道具(除了孩子)。 如果你想在调用<Icon/>
时传递道具,你可以使用React.ComponentType<SomePropsType>
。
您可以使用 JSX.Element 而不是 React.ReactNode,这就是@heroicons/react
作为类型返回的内容
页脚社交图标(为本示例添加了 TableIcon)
import { FC } from 'react';
import cn from 'classnames';
import {
Facebook,
Instagram,
SquareLogo
} from '@/components/UI/Icons';
import { TableIcon } from '@heroicons/react/solid';
import css from './footer.module.css';
export interface FooterSocialProps {
href: string;
label: string;
id: number;
icon: JSX.Element;
}
export const footerSocial: FooterSocialProps[] = [
{
href: 'https://www.facebook.com/thefaderoominc/?ref=py_c',
label: 'Facebook',
id: 0,
icon: <Facebook />
},
{
href: 'https://www.instagram.com/thefaderoomhighlandpark/',
label: 'Instagram',
id: 1,
icon: <Instagram />
},
{
href: 'https://squareup.com/gift/MLHZCDVC0MKB1/order',
label: 'Square Giftcards',
id: 2,
icon: <SquareLogo />
},
{
href: 'https://stackoverflow.com/example',
label: 'Table Icon',
id: 3,
icon: <TableIcon />
}
];
export interface FooterSocialPropsFC {
className?: string;
}
const FooterSocial: FC<FooterSocialPropsFC> = ({
className
}) => {
return (
<div className={cn(css.socialRoot, className)}>
{footerSocial.map((social, i) => (
<div key={++i}>
<a
title={social.label}
target='__blank'
href={social.href}
className={cn(
css.socialLink,
'text-olive-300 hover:text-olive-400 text-opacity-80'
)}
>
<span className='sr-only'>
{`External Link to The Fade Room's ${social.label} page`}
</span>
{social.icon}
</a>
</div>
))}
</div>
);
};
export default FooterSocial;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.