简体   繁体   中英

How to use "react-icons" in loop (Map method) in ReactJS 😅

I'm using React-icons in my ReactJS project and I just wanted to loop (by Map method) the specific icons in each JSX field when data is render.

In other word, I want this {`<${e.contact.icons}/>`} in JSX code. Here is my code section:-

Here is, I import some icons for React icons .

import { FaBeer, Fa500Px, FeAccusoft } from "react-icons/fa";

Here is a data array which I want to render in JSX .

const data = [
  {
    contact: [
      {
        title: 'contact',
        icons: 'FaBeer',
      },
      {
        title: 'contact',
        icons: 'Fa500Px',
      },
      {
        title: 'contact',
        icons: 'FaAccusoft',
      },
    ],
  },
]

And this is my component in down below. Which I'm using icons . You get little idea what I want to do.

const contact = () => {
  return (
    <>
      {data.map((e, i) => {
        return (
          <>
            <div className="text-area">
              <span> {`<${e.contact.icons}/>`} </span>
            </div>
          </>
        );
      })}
    </>
  );
};

export default contact;

I'm trying to use like this {`<${e.contact.icons}/>`} , but is not working. When I see in browser. It's look like this.

<FaBeer/>
<Fa500Px/>
<FaAccusoft/>

It's just return like a text, but I want to get icons .

Any suggestion ?

You can also use Parser() from html-react-parser. https://github.com/remarkablemark/html-react-parser

const parse = require('html-react-parser');
{parse(`<${e.contact.icons}/>`)};

https://codesandbox.io/s/fervent-goldwasser-y83cn?file=/src/App.js

import { FaBeer, Fa500Px, FaAccusoft } from "react-icons/fa";

// here is data for I want to show

const data = [
  {
    contact: [
      {
        title: "contact",
        subtitle: "get in touch",
        icons: FaBeer
      },
      {
        title: "contact",
        subtitle: "get in touch",
        icons: Fa500Px
      },
      {
        title: "contact",
        subtitle: "get in touch",
        icons: FaAccusoft
      }
    ]
  }
];

const contact = () => {
  return (
    <>
      {data.map((e, i) => {
        return (
          <>
            {e.contact.map((e, i) => {
              return (
                <div className="text-area" key={i}>
                  <h1 className="title">{e.title}</h1>
                  <h2 className="subtitle">{e.subtitle}</h2>
                  <span>
                    <e.icons />
                  </span>
                </div>
              );
            })}
          </>
        );
      })}
    </>
  );
};

export default contact;

It seems that the current answers already addresses the problem, so this only attempts to add small improvement for the solution. Here is an approach I tried in a similar situation.

Simplified demo on: stackblitz

This will keep data the same as posted in the question as it might need to be fetched:

const data = [
  {
    contact: [
      {
        title: 'contact',
        icons: 'FaBeer',
      },
      {
        title: 'contact',
        icons: 'Fa500Px',
      },
      {
        title: 'contact',
        icons: 'FaChrome',
      },
    ],
  },
];

Define an object with the imported icons as static data:

import { FaBeer, Fa500Px, FaChrome } from 'react-icons/fa';
const icons = { FaBeer, Fa500Px, FaChrome };

In the output, the icon can taken out from static data, and rendered on condition:

const Contact = () => {
  return (
    <>
      {data.map((e, i) => (
        <React.Fragment key={i}>
          {e.contact.map((item, index) => {
            const Icon = icons?.[item.icons];
            return (
              <div key={index} className="text-area">
                <span>{Icon && <Icon size="3em" color="hotpink" />}</span>
              </div>
            );
          })}
        </React.Fragment>
      ))}
    </>
  );
};

export default contact;

Well, the option of importing FaIcon-s and putting them into "data" array looks pretty nice:

import { FaBeer, Fa500Px, FaAccusoft } from "react-icons/fa";

const data = [
  {
    contact: [
      {
        title: "contact",
        subtitle: "get in touch",
        icons: FaBeer,
      },
...

On the other hand possibility of generating components "dynamically" by their string name could be still implemented.

Firstly, I find usefull following article: React / JSX Dynamic Component Name

Next, I've created a new FaIconDynamic component:

import {
    AiFillAccountBook,
    AiFillAlert,
    AiFillAlipayCircle,
    AiFillAndroid,
} from 'react-icons/ai';

export const FaIconDynamic = ({ type }) => {
    const FaIcon = components[type];
    return <FaIcon></FaIcon>;
};

const components = {
    AiFillAccountBook,
    AiFillAlert,
    AiFillAlipayCircle,
    AiFillAndroid,
};

And then that's pretty easy to generate any registered above fa-icon, fe:

function App() {
    return (
        <>
            <FaIconDynamic type={'AiFillAccountBook'} />
            <FaIconDynamic type={'AiFillAlert'} />
            <FaIconDynamic type={'AiFillAlipayCircle'} />
            <FaIconDynamic type={'AiFillAndroid'} />
        </>
    );
}

Of course, both approaches have their pros and cons and could be more benefitial in some situations over each other

You cannot use strings to represent React Component Types, instead you can use the imported ComponentType itself.

import { FaBeer, Fa500Px, FaAccusoft } from "react-icons/fa";

// here is data for I want to show

const data = [
  {
    contact: [
      {
        title: "contact",
        subtitle: "get in touch",
        icons: FaBeer,
      },
      {
        title: "contact",
        subtitle: "get in touch",
        icons: Fa500Px,
      },
      {
        title: "contact",
        subtitle: "get in touch",
        icons: FaAccusoft,
      },
    ],
  },
];

const Contact = () => {
  return (
    <>
      {data.map((e, i) => {
        const Icon = e.contact.icons;
        return (
          <>
            <div className="text-area">
              <h1 className="title">{e.contact.title}</h1>
              <h2 className="subtitle">{e.contact.subtitle}</h2>
              <span><Icon /></span>
            </div>
          </>
        );
      })}
    </>
  );
};

export default Contact;

Note how the rendering of Icon changes as well

I have gotten this type of method and I manage to do what I want

import React from "react";
import { render } from "react-dom";
import * as FontAwesome from "react-icons/lib/fa";

const Icon = props => {
  const { iconName, size, color } = props;
  const icon = React.createElement(FontAwesome[iconName]);
  return <div style={{ fontSize: size, color: color }}>{icon}</div>;
};

const App = () => {
  const iconString = "FaBeer";
  const beer = React.createElement(FontAwesome[iconString]);
  return (
    <div>
      <h2>Start editing to see some magic happen {"\u2728"}</h2>
      <FontAwesome.FaBeer />
      <div style={{ fontSize: 24, color: "orange" }}>{beer}</div>
      <Icon iconName={"FaBeer"} size={12} color="orange" />
    </div>
  );
};


----------


render(<App />, document.getElementById("root"));

https://codesandbox.io/s/o715x22m4z?file=/src/index.js:0-737`enter code here`

thank to〈Evie.Codes〉.

import { FaBeer, Fa500Px, FeAccusoft } from "react-icons/fa";

note: there is a typo in the name of the icon you imported.. it should be FaAccusoft

my suggestion for your question is to store the Icon components themselves in the object property.. so instead of storing it as string: "FaBeer" ... store it as a component: <FaBeer /> directly inside the object property.. like this:

const data = [
  {
    contact: [
      {
        title: "contact-1",
        icons: <FaBeer />
      },
      {
        title: "contact-2",
        icons: <Fa500Px />
      },
      {
        title: "contact-3",
        icons: <FaAccusoft />
      }
    ]
  }
];

and then you can simply loop over them

const Contact = () => {
  return (
    <>
      {data.map((e, i) => {
        return (
          <>
            {e.contact.map((c) => {
              return (
                <div className="text-area">
                  {c.title}
                  <span>
                    {c.icons} // you simply call it like this and the icon will be rendered
                  </span> 
                </div>
              );
            })}
          </>
        );
      })}
    </>
  );
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM