arctic
arctic

Reputation: 819

Looping to reduce redundancy in React

Here is a link to a working example of the site: https://codesandbox.io/s/eloquent-kapitsa-kk1ls

I have remove some personal info like my name and deep links for privacy.

I am trying to reduce the complexity of Buttons.js. I am rendering 4 different buttons although each follows the same syntax withholding the icon and the icon's hover text.

Buttons.js:

import React, { Component } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import registerIcons from "./FontAwesome";

registerIcons();

let size = "3x";

class Buttons extends Component {
  render() {
    return (
      <div>
        <span className="button">
          <a
            href="https://github.com/"
            target="_self"
            rel="noopener noreferrer"
          >
            <FontAwesomeIcon
              className="icon"
              icon={["fab", "github"]}
              size={size}
            />
            <span className="icon_title">Github</span>
          </a>
        </span>

        <span className="button">
          <a
            href="https://www.linkedin.com/"
            target="_self"
            rel="noopener noreferrer"
          >
            <FontAwesomeIcon
              className="icon"
              icon={["fab", "linkedin"]}
              size={size}
            />
            <span className="icon_title">LinkedIn</span>
          </a>
        </span>

        <span className="button">
          <a href="..." target="_self" rel="noopener noreferrer">
            <FontAwesomeIcon
              className="icon"
              icon={["fas", "file-alt"]}
              size={size}
            />
            <span className="icon_title">Resume</span>
          </a>
        </span>

        <span className="button">
          <a href="mailto:{email}" target="_self" rel="noopener noreferrer">
            <div className="temp">
              <FontAwesomeIcon
                className="icon"
                icon={["fas", "paper-plane"]}
                size={size}
              />
              <span className="icon_title">Email me</span>
            </div>
          </a>
        </span>
      </div>
    );
  }
}

export default Buttons;

I have looked online for information regarding looping in React to render elements but I cannot find any concrete examples of it being done. From my understanding, variables would be created in Buttons.js - each holding an array with 4 items (1 for each button). I would then use a for loop to construct each element and append it to the previous element.

Here is one example. However, the elements rendered seem to be less complex than the ones I have.

Can someone provide a template for looping through my buttons to reduce the redundancy in my code? I am fine with you editing anywhere in my environment: https://codesandbox.io/s/eloquent-kapitsa-kk1ls?file=/src/Buttons.js

Upvotes: 1

Views: 289

Answers (1)

Rodrigo Amaral
Rodrigo Amaral

Reputation: 1382

When your children components are all similar, it might be a good idea to create a custom component for each item and an array of props, like this:

const DATA = [
  {
    label: "Github",
    size,
    icon: ["fab", "github"],
    href: "https://github.com/"
  },
  {
    label: "LinkedIn",
    size,
    icon: ["fab", "linkedin"],
    href: "https://www.linkedin.com/"
  },
  {
    label: "Resume",
    size,
    icon: ["fas", "file-alt"],
    href: "..."
  },
  {
    label: "Email me",
    size,
    icon: ["fas", "paper-plane"],
    href: "mailto:{email}",
    temp: true
  }
];

const Icon = ({ label, size, icon, href, temp }) => {
  const inner = (
    <>
      <FontAwesomeIcon className="icon" icon={icon} size={size} />
      <span className="icon_title">{label}</span>
    </>
  );

  return (
    <span className="button">
      <a href={href} target="_self" rel="noopener noreferrer">
        {temp ? <div className="temp">{inner}</div> : inner}
      </a>
    </span>
  );
};

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

https://codesandbox.io/s/vibrant-davinci-6r9xs?file=/src/Buttons.js

Upvotes: 1

Related Questions