如何使用它的snake_case名称(React,material-ui)动态加载图标

时间:2019-05-29 22:43:07

标签: reactjs icons material-design material-ui

通常我会通过直接导入per the material-ui instructions来使用Material-ui图标。

但是我有一个文本标签,它是实际的图标名称(如calendar_view_day),需要动态地从中获取和呈现图标组件。

我该怎么办?

render() {
  return (
    <Icon name="calendar_view_day" color="primary" />
  )
}

代替:

render() {
  return (
    <CalendarViewDay color="primary" />  // Imported by name
  )
}

2 个答案:

答案 0 :(得分:2)

好,所以我对此大为思索。

正确答案

结果material-ui包含一个图标组件,该组件允许您执行此操作...并且它本身可以转换名称,因此可以接受蛇,pascal和其他变体。

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

...

render() {
  return (
    <Icon>{props.iconName}</Icon>
  )
}

先前的答案(有效但过度的矫over过正)

创建函数以用于

...然后使用material-ui图标组件。

代码如下:

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

function upperFirst(string) {
  return string.slice(0, 1).toUpperCase() + string.slice(1, string.length)
}

function fixIconNames(string) {
  const name = string.split('_').map(upperFirst).join('')
  if (name === '3dRotation') {
    return 'ThreeDRotation'
  } else if (name === '4k') {
    return 'FourK'
  } else if (name === '360') {
    return 'ThreeSixty'
  }
  return name
}

...

render() {
  const iconName = fixIconNames(props.iconName)
  return (
    <Icon>{props.iconName}</Icon>
  )
}

答案 1 :(得分:0)

正如上面对 thclark 回答的评论所述,使用 Icon 组件的解决方案将使用 Material-UI 图标的字体版本,其中不包含完整的图标集.

通过使用相同的方法来获得正确的图标名称(从 thclark 中借来)并结合 React.createElement 来实现。我在 TypeScript 中做到了这一点,在 vanilla javascript 中更容易。这是 TS 版本 (dynamicIcon.tsx) 中的组件,也可在 this repo 中使用:

import * as React from 'react';
import * as Icons from '@material-ui/icons/';

type IconType = typeof import('@material-ui/icons/index');

interface DynamicIconProps {
    iconName: string,
    className: string
}

function upperFirst(string:string) {
    return string.slice(0, 1).toUpperCase() + string.slice(1, string.length)
}
  
function fixIconNames(string:string) {
    const name = string.split('-').map(upperFirst).join('')
    if (name === '3dRotation') {
        return 'ThreeDRotation'
    } else if (name === '4k') {
        return 'FourK'
    } else if (name === '360') {
        return 'ThreeSixty'
    }
    return name;
}

export default class DynamicIcon extends React.Component<DynamicIconProps> {
    constructor(props: DynamicIconProps) {
        super(props);
    }

    render() {
        return React.createElement(Icons[fixIconNames(this.props.iconName)! as keyof IconType], {className: this.props.className});
    }
}