来自配置的 React 和 Typescript 动态组件
Posted
技术标签:
【中文标题】来自配置的 React 和 Typescript 动态组件【英文标题】:React and Typescript dynamic component from config 【发布时间】:2021-08-13 05:28:50 【问题描述】:我正在尝试使用 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.
我在没有按预期工作的打字稿的情况下做了类似的事情——谁能告诉我我做错了什么?
【问题讨论】:
【参考方案1】:React.ReactNode
是渲染组件的类型。例如:
const a: React.ReactNode = <TableIcon />
如果你想传入一些渲染 JSX,那就是你会使用的。但听起来你想传入一个没有道具的功能组件,然后然后被渲染。
React.FC
是没有道具的反应功能组件的通用类型。这可能就是你想要的类型。
type route =
icon: React.FC,
path: string,
title: string,
Playground
【讨论】:
【参考方案2】: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>
))
-
传递一个可调用的组件。通常你需要给它一个大写的名字以便通过 JSX 调用它。不知何故
<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>
。
【讨论】:
【参考方案3】:您可以使用 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://***.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;
【讨论】:
以上是关于来自配置的 React 和 Typescript 动态组件的主要内容,如果未能解决你的问题,请参考以下文章
使来自 react-intl 的 FormattedMessage 中的 id 继承自自定义 TypeScript 接口以启用 VS IntelliSense 和类型检查
使用来自使用旧版 Typescript 确定类型的 Typescript 定义文件
使用 airbnb 和 prettier 扩展的 ESLint 配置,用于使用 typescript、jest 和 react-hooks 的 react 项目