React如何动态地选择一个组件进行渲染

264 阅读1分钟

我需要在一个菜单中呈现一个项目列表,每个项目都有自己的图标。

我最初在一个菜单中硬编码了这个组件,像这样。

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} />