1

How do I set a custom tag in React?

Each import is a JSX Element. For example, GitHub is imported from a file that looks like this:

import React from 'react';

const GitHub = () => (
    <svg role="img" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" height="1.5rem" width="1.5rem">
        <title>GitHub Icon</title>
        <path d="M171.25 408.36c0 2.06-2.37 3.7-5.37 3.7-3.4.32-5.78-1.33-5.78-3.7 0-2.07 2.38-3.72 5.37-3.72 3.1-.31 5.78 1.36 5.78 3.72zm-32.1-4.65c-.72 2.07 1.34 4.44 4.44 5.06 2.68 1 5.78 0 6.4-2.06.62-2.06-1.34-4.44-4.44-5.37-2.69-.72-5.68.3-6.4 2.37zm45.62-1.71c-3 .72-5 2.68-4.74 5.06.31 2.06 3 3.4 6.09 2.68 3.09-.72 5-2.68 4.74-4.75-.26-2.07-3.09-3.34-6.09-3zM252.7 6.4C109.52 6.4 0 115.09 0 258.27c0 114.47 72.05 212.44 175 246.9 13.21 2.39 17.86-5.77 17.86-12.48 0-6.4-.31-41.7-.31-63.38 0 0-72.26 15.49-87.44-30.76 0 0-11.76-30-28.69-37.78 0 0-23.64-16.21 1.65-15.9 0 0 25.7 2.07 39.84 26.64 22.61 39.84 60.49 28.38 75.26 21.57 2.37-16.52 9.08-28 16.51-34.8-57.68-6.4-115.95-14.75-115.95-114.05 0-28.4 7.84-42.63 24.36-60.8-2.68-6.71-11.46-34.38 2.68-70.1 21.58-6.7 71.23 27.88 71.23 27.88a242.6 242.6 0 0164.83-8.78 242.52 242.52 0 0164.82 8.78s49.65-34.68 71.23-27.87c14.14 35.82 5.37 63.38 2.68 70.09 16.52 18.27 26.63 32.5 26.63 60.8 0 99.6-60.8 107.56-118.5 114.06 9.5 8.16 17.55 23.64 17.55 47.9 0 34.79-.31 77.83-.31 86.3 0 6.7 4.75 14.86 17.86 12.49C442 470.7 512 372.74 512 258.27 512 115.09 395.87 6.4 252.7 6.4zm-152.36 356c-1.35 1-1 3.4.72 5.37 1.65 1.65 4 2.37 5.37 1 1.34-1 1-3.4-.73-5.37-1.65-1.6-4.02-2.32-5.36-.98zm-11.15-8.36c-.73 1.34.31 3 2.37 4 1.65 1 3.72.72 4.44-.73.72-1.45-.31-3-2.37-4-2.07-.6-3.72-.31-4.44.75zm33.44 36.75c-1.65 1.34-1 4.44 1.34 6.4 2.38 2.37 5.37 2.68 6.71 1 1.35-1.34.73-4.44-1.34-6.4-2.27-2.32-5.34-2.63-6.71-.98zm-11.77-15.18c-1.65 1-1.65 3.72 0 6.1 1.65 2.38 4.44 3.4 5.79 2.37 1.65-1.34 1.65-4 0-6.4-1.45-2.37-4.13-3.41-5.79-2.07z"/>
    </svg>
);

export default GitHub;

The other icons are imported from their respective files in the same format. I now want to loop through DATA to render each icon.

import React, { Component } from 'react';

import GitHub from './../assets/GitHub'
import LinkedIn from './../assets/LinkedIn'
import Email from './../assets/Email'


const DATA = [
    {
        href: "...",
        aria: "...",
        icon: GitHub,
        label: "...",
    },
    {
        href: "...",
        aria: "...",
        icon: LinkedIn,
        label: "...",
    },
    {
        href: "...",
        aria: "...",
        icon: Email,
        label: "...",
    }
];

const Button = ({ href, aria, icon, label }) => {
    return (
        <span className="button-container">
            <a className="button" href={href} target="_self" aria-label={aria} rel="noopener noreferrer">
                <{icon} className="icon"/>
                <span className="icon_title">{label}</span>
            </a>
        </span>
    );
};

class Buttons extends Component {
    render() {
        return (
            <div>
                {DATA.map((props, i) => (
                    <Button {...props} key={i} />
                ))}
            </div>
        );
    }
}

export default Buttons;

The line of code is where I am having difficulty is <{icon} className="icon"/>. I do not know how to set a custom HTML tag while looping

Also, any other feedback would be appreciated. In DATA, should I store each icon as an alias to the import or should I instead have icon: "GitHub"?

Thanks!

3
  • did you try out the other answers? Commented Sep 5, 2020 at 21:39
  • Yes, currently working with your solution and trying to iron out the css Commented Sep 5, 2020 at 21:50
  • i added a running example and i check that my two solutions work and Nicholas Tower's solution Commented Sep 5, 2020 at 22:14

2 Answers 2

3

You'll need to rename it to Icon with a capital I (this convention distinguishes custom components from built in ones like <div>), but other than that you use it just like you would any other component:

const Button = ({ href, aria, icon: Icon, label }) => {
    return (
        <span className="button-container">
            <a className="button" href={href} target="_self" aria-label={aria} rel="noopener noreferrer">
                <Icon className="icon"/>
                <span className="icon_title">{label}</span>
            </a>
        </span>
    );
};
Sign up to request clarification or add additional context in comments.

Comments

2

Since React exige capitalized component names, you could assign that prop to a local variable called Icon then use render it as JSX :


const Button = ({ href, aria, icon, label }) => {
   let Icon=icon;
    return (
        <span className="button-container">
            <a className="button" href={href} target="_self" aria-label={aria} rel="noopener noreferrer">
                <Icon className="icon"/>
                <span className="icon_title">{label}</span>
            </a>
        </span>
    );
};

or set the icons as elements in the DATA array like :

const DATA = [
    {
        href: "...",
        aria: "...",
        icon: <GitHub className="icon" />,
        label: "...",
    },
   ...

then render it as follows :

const Button = ({ href, aria, icon, label }) => {
    return (
        <span className="button-container">
            <a className="button" href={href} target="_self" aria-label={aria} rel="noopener noreferrer">
                {icon}
                <span className="icon_title">{label}</span>
            </a>
        </span>
    );
};

Please check this example

Comments

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.