我需要在一个菜单中呈现一个项目列表,每个项目都有自己的图标。
我最初在一个菜单中硬编码了这个组件,像这样。
const menu = [
{
title: 'Home',
icon: <HomeIcon className="mr-3 ml-1 h-5 w-5" />
},
{ title: 'Notifications', icon: <BellIcon className="mr-3 ml-1 h-5 w-5" /> },
{ title: 'Profile', icon: <UserIcon className="mr-3 ml-1 h-5 w-5" /> },
]
使用非常酷的@heroicons/react 包。
在JSX中,我对menu 数组进行迭代,以显示{item.icon}
但后来我不得不根据应用程序的响应状态来改变我所使用的Tailwind类,为此我使用了react-responsive 包。
我决定传递一个字符串来代替,所以我首先这样做。
const menu = [
{ title: 'Home', icon: 'HomeIcon' },
{ title: 'Notifications', icon: 'BellIcon' },
{ title: 'Profile', icon: 'UserIcon' },
]
const Icon = (props) => {
const { name } = props
let icon = null
if (name === 'HomeIcon') icon = HomeIcon
if (name === 'BellIcon') icon = BellIcon
if (name === 'UserIcon') icon = UserIcon
return React.createElement(icon, { ...props })
}
...
<Icon name={item.icon} />
另一个可能的解决方案是使用一个对象来查找组件,而不是一堆if 的检查。
const icons = {
HomeIcon,
BellIcon,
UserIcon,
}
const Icon = (props) => {
const { name } = props
const TheIcon = icons[name]
return <TheIcon {...props} />
}
<Icon name={item.icon} />
我不得不使用
TheIcon,因为按照惯例,React组件以大写字母开头。
这已经很好了,但我后来意识到我可以用更简单的方法来做,即使用实际的组件而不是menu 数组中的字符串。
const menu = [
{ title: 'Home', icon: HomeIcon },
{ title: 'Notifications', icon: BellIcon },
{ title: 'Profile', icon: UserIcon },
]
const Icon = (props) => {
const { icon } = props
const TheIcon = icon
return <TheIcon {...props} />
}
...
<Icon icon={item.icon} />