首页 > 解决方案 > 从数组中渲染 Material-UI 图标

问题描述

背景信息:
我正在使用 react 和 material-ui。
为了保持代码干净,我从一个 const 数组填充菜单项,如下所示:

const menuItems = [
  { label: "Home", path: "/home" },
  { label: "Accounts", path: "/accounts" },
  { label: "Organizations", path: "/organizations" },
];

数组中的每一项都是一个包含标签和重定向路径的对象。我在渲染时映射项目。很基础。

问题:
我想在 menuItems 数组中包含一个 material-ui 图标组件,以便可以在标签旁边呈现图标。但我找不到通过名称字符串引用图标的方法
https://material-ui.com/components/material-icons/

可能的解决方案:

  1. 将图标组件放入字符串中: { label: "Accounts", path: "/accounts" }, icon: "<AccountBox/>"}但后来我需要以某种方式将字符串评估为 jsx。我不知道怎么做。

  2. 制作一个反应功能组件,根据道具呈现不同的图标,例如:<IconSwitch icon = {"accountIcon"} />并在 RFC 中硬编码不同的图标。不漂亮,但应该工作。

  3. 使用不同的图标,例如 svg 图标或字体图标,可以通过名称字符串引用。

关于如何做到这一点的任何建议?谢谢

标签: reactjsmaterial-ui

解决方案


图标字体

您可以使用该Icon组件。https://material-ui.com/components/icons/#icon-font-icons

要使用图标,只需将图标名称(字体连字)与 Icon 组件包装起来,例如:

import Icon from '@material-ui/core/Icon';

<Icon>star</Icon>

https://codesandbox.io/s/material-demo-forked-sj66h?file=/demo.tsx

假设您使用适当的图标连字设置菜单项:

  const menuItems = [
    { label: "Home", path: "/home", icon: "home" },
    { label: "Accounts", path: "/accounts", icon: "account_circle" },
    { label: "Organizations", path: "/organizations", icon: "settings" }
  ];

然后你可以映射它们:

      {menuItems.map(({ label, icon }) => {
        return (
          <span key={label}>
            {label} <Icon>{icon}</Icon>
          </span>
        );
      })}

SVG 图标

如果您想使用 SVG 图标而不是基本图标,我建议您只提取您计划使用的 SVG 图标,以便让您不使用的图标从生成的包中进行树状抖动。摇树的能力是使用 SVG 图标而不是字体图标的一个很好的理由。

import { Home, AccountCircle, Settings, AddCircle } from "@material-ui/icons";

如果您想允许用户输入所有图标或提前不知道将显示哪些图标,您可以从Jonathan's answer@material-ui/icons中导入所有内容。

如果您没有将图标列表放入需要能够被字符串化的东西(即 Redux/通过 API 调用发送),那么您可以直接将图标放入数组并渲染它们:

  const menuItems: MenuItem[] = [
    { label: "Home", path: "/home", icon: <Home /> },
    { label: "Accounts", path: "/accounts", icon: <AccountCircle /> },
    { label: "Organizations", path: "/organizations", icon: <Settings /> }
  ];

 // Rendering:

      {menuItems.map(({ label, icon }) => {
        return (
          <span key={label}>
            {label} {icon}
          </span>
        );
      })}

如果您要将图标放在需要字符串化的地方,上述方法将不起作用,因此我建议您将要使用的图标放入对象中以映射它们。这样你就有一个字符串到图标映射。

示例:https ://codesandbox.io/s/material-icons-svg-udcv3?file=/demo.tsx

import { Home, AccountCircle, Settings, AddCircle } from "@material-ui/icons";

const icons = {
  Home,
  AccountCircle,
  Settings
};

在上面的例子中(即从数组中渲染图标)

interface MenuItem {
  label: string;
  path: string;
  icon: keyof typeof icons;
}

  const menuItems: MenuItem[] = [
    { label: "Home", path: "/home", icon: "Home" },
    { label: "Accounts", path: "/accounts", icon: "AccountCircle" },
    { label: "Organizations", path: "/organizations", icon: "Settings" }
  ];

// Rendering:

      {menuItems.map(({ label, icon }) => {
        const Icon = icons[icon];
        return (
          <span key={label}>
            {label} <Icon />
          </span>
        );
      })}

推荐阅读