Home > Software design >  Map through nested object to display image NextJS
Map through nested object to display image NextJS

Time:07-23

I have to make some repeatable components, and I was wondering if I could map through an object to get a result like this: desired result

First of all, I created the object, storing all the data:

const tehnologii = [
  {
    title: "Programare",
    tech: {
      name: ["Python", "Java", "C  ", "Git"],
      img: ["python", "java", "cpp", "git"]
    },
  },
  {
    title: "Web Development",
    tech: {
      name: ["html", "css", "javascript", "react", "php", "laravel", "c-sharp", "dot NET"],
      img: ["html", "css", "javascript", "react", "php", "laravel", "c-sharp", "net"]
    },
  },
  {
    title: "Design",
    tech: {
      name: ["photoshop", "illustrator", "invision", "miro", "zeplin"],
      img: ["photoshop", "illustrator", "invision", "miro", "zeplin"]
    },
  },
  {
    title: "DevOps",
    tech: {
      name: ["docker", "jenkins", "ansible", "aws", "terraform"],
      img: ["docker", "jenkins", "ansible", "aws", "terraform"]
    },
  },
  {
    title: "Skill-up",
    tech: {
      name: ["sql", "mysql", "scrum", "linux"],
      img: ["sql", "mysql", "scrum", "linux"]
    },
  },
  {
    title: "Testare",
    tech: {
      name: ["testare software", "selenium"],
      img: ["testare", "selenium"]
    },
  },
  {
    title: "Alte Cursuri",
    tech: {
      name: ["Excel"],
      img: ["excel"]
    },
  }
 
];

Usually I'm using something like this to map through object and display images:

{tehnologii.map((tech, index) => (
    <Column key={index}>
      <img src={require(`./img/${tech.img}.svg`).default.src} alt={tech.name} />
    </Column>
  ))}

But this would work only for a basic structure like this:

const tehnologii = [
  {
    name: "amdaris",
    img: "amdaris",
  },
  {
    name: "unifiedPost",
    img: "unified-post",
  },
]

How could I map a more complex structure, like shown above, so I could get a component with a Title, that contains images of included techs?

P.S. I used .default.src because I'm working with NextJS

CodePudding user response:

I hope the following would help you!

{tehnologii.map((item, index) => (
    <div key={index}>
       <h1>{item.title}</h1>
       <Column>
         <img src={require(`./img/${item.tech.img}.svg`).default.src} alt={tech.name} />
       </Column>
    </div>
  ))}

CodePudding user response:

I would like to suggest an alternative approach to the solution you are trying to achieve. This involved using icons from packages like react-icons or MUI, instead of using jpg/png images wherein you will have to mess around with sizes and layouts(for next/image). You can take a look at how I did this exact thing for my portfolio website on my personal-portfolio-github-repo

First, lets tackle the problem of showing images:

If you look into the data folder, it contains an array of all my projects, much simpler than what you are using in your case. Instead of storing the names and icons of the technologies separately, I am directly storing the Icon Components of those inside the "techstack" array. Then, in the project-card-component (lines 46 to 52), I am looping through the techstack to display each icon. In my honest opinion, this way you won't have to play around with pixel sizes and layouts, and hence, is simpler.

Now, for the data structure problem, you can do the following:

Using data structured as:

import { Logo1, Logo2, Logo3 } from "someLibrary";

const tehnologii = [
  {
    title: "Programare",
    tech: [Logo1, Logo2, Logo3]
  },
]

The render method of your functional component must be as follows:

tehnologii.map((item, index) => {
const itemTitle = item.title;
const itemTech = item.tech;
return(<div key={index}>
    <p>{itemTitle}</p>
    <span>{itemTech.map((TechLogo, index1) => <TechLogo key={index1} />)}</span>
    </div>)
})

Please refer to my GitHub(mentioned above) if you are stuck, or just write down a comment and I will get back to you.

  • Related