2

ok guys I have a problem.

I need render a list which has a title and a icon . and I Want to render it dynamic with map method.

This is the backend api object(Its more than 2 :D )

// icons are Material UI Icon component
const list = [
{title: 'Vehicle', icon: 'DirectionsCarFilledOutlined'},
{title: 'Electronic', icon: 'PhoneIphoneOutlined'},
]

What I have to do is to render this icon COMPONENT dynamic

something like this

import {
  DirectionsCarFilledOutlined,
  PhoneIphoneOutlined,
} from "@mui/icons-material";


const list = [
{title: 'Vehicle', icon: 'DirectionsCarFilledOutlined'},
{title: 'Electronic', icon: 'PhoneIphoneOutlined'},
]

              {list.map(({ title, icon }) => {
                return (
                  <div>
                    <p>{title}</p>
                    <div>{<icon />}</div> // Problem is here. IDK How to render it 
                  </div>
                );
              })}

I Wrote switch case for this problem but that's bad and if we add new items to api those lists won't have icon.

Is there anyway to render this Icons dynamic ?

3
  • Capitalize the name. ({icon}) => { const Icon = icon; ... then render it <Icon /> } Commented Sep 1, 2022 at 14:01
  • @OktayYuzcan Ty for ur replay. I tried that but in the inspect element instead of component we have <phoneiphoneoutlined></phoneiphoneoutlined> Commented Sep 1, 2022 at 14:04
  • icon value has to be component, not string. If the data is from server, you have to create an object where you get the component itself based on string value. Something like: components: {'DirectionsCarFilledOutlined': DirectionsCarFilledOutlined, ...} Commented Sep 1, 2022 at 14:25

2 Answers 2

2

You can solve your problem by using React.lazy to LazyLoad icons, given that the icon value corresponds to an exact path from @mui/icons-material.

To do so, first we need to define a lazy function that can return non-default exports, since React.lazy expects to return a default import


// iconName is still undefined, but we'll get to it
const Icon = lazy(() =>
  import("@mui/icons-material").then(module => ({ default: module[iconName] }))
);

Then, we'll write an Item component, which receives iconName as a prop and LazyLoads it, utilizing React.Suspense to allow for the component to be rendered.


import React, {lazy, Suspense} from 'react'

const Item = ({title, iconName}) => {
  const Icon = lazy(() =>
    import("@mui/icons-material").then(module => ({ default: module[iconName] }))
  );

  return (
    <div>
      <p>{title}</p>
      <div>
        <Suspense fallback={<></>}>
          <Icon/>
        </Suspense>
      </div>
    </div>
  )
}

You should then import Item inside your component and return Items from your map.

Sign up to request clarification or add additional context in comments.

Comments

0

Hope this could be the solution for you.

You can directly set the icon element imported from @mui/icons-material as the value of the icon of the list item.

import {
  DirectionsCarFilledOutlined,
  PhoneIphoneOutlined,
} from "@mui/icons-material";


const list = [
  {title: 'Vehicle', icon: DirectionsCarFilledOutlined},
  {title: 'Electronic', icon: PhoneIphoneOutlined},
]

... in render part

          {list.map(({ title, icon }) => {
            return (
              <div>
                <p>{title}</p>
                <div><icon /></div> // Problem is here. IDK How to render it 
              </div>
            );
          })}

1 Comment

ty for your replay. but the data is coming from backend and everything is string

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.