Skip to content

Trying to build React Component that can iterate over a nested data structure and produce styled HTML elements based on type

I have a nested data structure I’m getting back from an API that contains sections of text as objects inside of an array.

I’m trying to iterate over the initial array of sections, check to see what type the section is, and then based on the type iterate over the copy array to style and render each string as the appropriate HTML element.

The problem I’m running into is that I’m trying to accomplish this by using map and then a switch statement and then another map for each copy section and nothing is rendering.

Here’s a CodeSandbox I created as a mock up of the problem

This is my current component:

import React from "react";
import styled from "styled-components";

function renderElement(sections) {
  if (sections) {
    sections.map((section) => {
      switch (section.textType) {
        case "title":
          return section.copy.map((text) => <Title>{text}</Title>);
        case "subtitle":
          return section.copy.map((text) => <Subtitle>{text}</Subtitle>);
        case "body":
          return section.copy.map((text) => <Body>{text}</Body>);
        default:
          return section.copy;
      }
    });
  }
}

const TextComponent = (props) => {
  const { sections } = props;

  return <>{renderElement(sections)}</>;
};

export default TextComponent;

const Title = styled.h1`
  font-size: 28px;
`;

const Subtitle = styled.h4`
  font-size: 22px;
`;

const Body = styled.p`
  font-size: 16px;
`;

And this is the data structure:

const data = {
  sections: [
    {
      textType: "title",
      copy: ["Doctor Strange"]
    },
    {
      textType: "subtitle",
      copy: ["As Earth’s Sorcerer Supreme, Doctor Strange wields arcane spells and mystical artifacts to defend the planet against malevolent threats.", "The one who protects your reality"]
    },
    {
      textType: "body",
      copy: [
        "Recognized the world over as one of the most brilliant neurosurgeons, Stephen Strange’s arrogance and self-centered nature grew alongside his skill until his ego far outweighed his career.",
        "Knowing his reliance on his medical abilities to support his affluent lifestyle, Strange began to seek a source of healing for his hands until the quest drained him of his resources and he faced a dark and uncertain future."
      ]
    }
  ]
}

Answer

Figured out what I was doing wrong and was able to display all elements correctly by pushing them to a second array within my function and returning that new array like so:

function renderElement(sections) {
  const elements = []
  
  if (sections) {
    sections.map((section) => {
      switch (section.textType) {
        case "title":
          return elements.push(section.copy.map((string) => <Title>{string}</Title>));
        case "subtitle":
          return elements.push(section.copy.map((string) => <Subtitle>{string}</Subtitle>));
        case "body":
          return elements.push(section.copy.map((string) => <Body>{string}</Body>));
        default:
          return section.copy;
      }
    });
  }
  return elements
}