How can I dynamically load an icon using its snake_case name (React, material-ui)

14,365

OK, so I massively overthought this.

Correct answer

Turns out material-ui includes an icon component that allows you to do this... and it converts names itself, so accepts snake, pascal and other variants. BEWARE this will massively increase bundle size, as pointed out in the comments. If you're bundle size constrained, you'll have to take a different approach of serving the icon SVGs from somewhere!

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

...

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

Previous answer (working but massive overkill)

Create function to:

...Then use the material-ui Icon component.

Here's the code:

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>
  )
}
Share:
14,365

Related videos on Youtube

thclark
Author by

thclark

Engineer and scientist turned businessman working in renewable energy. My company, Octue, is a platform for deployment of engineering applications and digital twins of plant - allowing many collaborators, stakeholders and suppliers to integrate their solutions together.

Updated on September 15, 2022

Comments

  • thclark
    thclark over 1 year

    Normally I'd use material-ui icons by importing them directly per the material-ui instructions.

    But I have a text tag, which is the actual icon name (like calendar_view_day) and need to get and render an icon component from it dynamically.

    How can I something like:

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

    Instead of:

    render() {
      return (
        <CalendarViewDay color="primary" />  // Imported by name
      )
    }
    
  • Navid
    Navid almost 5 years
    importing the whole Icon module from material-ui will resolve the functionality, but will explode the bundle! You can analyze the bundle size via React official guideline
  • thclark
    thclark almost 5 years
    Thanks @Navid, added a health warnign to my answer.
  • Vajk Hermecz
    Vajk Hermecz over 4 years
    This solution uses font icons instead of svg icons. Requires the used font to be loaded. See: material-ui.com/components/icons/#icon-font-icons
  • Jonas Rosenqvist
    Jonas Rosenqvist over 3 years
    The 'correct answer' only prints the string props.iconName for me, doesn't show the actual icon.
  • Patrice Thimothee
    Patrice Thimothee about 3 years
    @jonasRosenvist, you also need to include some link into your code: <link rel="stylesheet" href="fonts.googleapis.com/icon?family=Material+Icons" />
  • vkt
    vkt almost 3 years
    this solution worked for me - <Icon>save</Icon>; The icon name should be lower case without the "Icon" suffix. Something like ChevronRight - should be changed to chevron_right. You have import the material_icon CSS file in index.js