"TypeError: Cannot read property 'name' of undefined" when looping on JSON

Viewed 639

I have a JSON like this :

{
  "cards": [
    {
      "name": "aquaman",
      "img": "aquaman.png"
    },
    {
      "name": "batman",
      "img": "batman.png"
    },
    {
      "name": "captainamerica",
      "img": "captainamerica.png"
    },
    {
      "name": "deadpool",
      "img": "deadpool.png"
    },
    {
      "name": "flash",
      "img": "flash.png"
    },
    {
      "name": "greenlantern",
      "img": "greenlantern.png"
    },
    {
      "name": "ironman",
      "img": "ironman.png"
    },
    {
      "name": "spiderman",
      "img": "spiderman.png"
    },
    {
      "name": "ironfist",
      "img": "ironfist.png"
    },
    {
      "name": "thepunisher",
      "img": "thepunisher.png"
    },
    {
      "name": "wonderwoman",
      "img": "wonderwoman.png"
    },
    {
      "name": "xman",
      "img": "xman.png"
    }
  ]
}

and I want to loop on these objects and to render a div with a backgroundImage with the img property of every object,

I tried this, but it tells me:

TypeError: Cannot read property 'name' of undefined

import React, { useEffect, useState } from "react";
import cardsJson from "../../../utils/cards.json";

const [cards, setCards] = useState();

useEffect(() => {
    setCards(cardsJson.cards);
  }, [cards]);

{cards &&
            cards.map((card: any, index: number) => (
              <div key={card.name} className="cardHero">
                <div className="front"></div>
                <div
                  className="back"
                  style={{
                    backgroundImage: `url(${require(`../../../assets/images/${card.img}`)})`
                  }}
                ></div>
              </div>
            ))}

It looks like inside the map I can't get name or img for every card ?? And when I console log "cards", it show me the JSON like above with name and img properties

2 Answers

Assuming your code is wrapped in a function component (see below), it may be an issue with how you're importing / using cards.json. Also in the useEffect, make the dependency array [] instead of [cards]. I changed your code to this and it works:

import React, { useEffect, useState } from "react";
import cardsJson from "./cards.json";


export function Cards() {
  const [cards, setCards] = useState();

  useEffect(() => {
    console.log(cardsJson);
    setCards(cardsJson.cards);
  }, []);

  return (
    <div>
      {
        cards &&
        cards.map((card, index) => (
          <div key={card.name} className="cardHero">
            <div className="front">{card.name}</div>
            <div
              className="back"
            ></div>
          </div>
        ))
      }
    </div>
  );
}

Note I put the cards.json in the same folder as the Cards component, I'm not outputting the image and I updated the dependency array.

If you only want to display the cards there is no reason for them to be inside a useEffect. I recommend you to create a constant and initialize it with cardsJson.cards, like:

const cards = cardsJson.cards;

Or if you want to play with states, just initialize your state with cardsJson.cards, like:

const [cards, setCards] = useState(cardsJson.cards);
Related