How to import data from a JSON file in React?

Viewed 133

I am trying to import data from a JSON file (a list of animals) into a React component.

I am getting this error:

TypeError: Cannot read property 'map' of undefined.

I can't figure out why though, because it is defined in my Animal component.

Here is my json file:

[
    {
        "animalName":"lion",
        "animalPic": "images/lion",
        "animalSpecies": "Panthera leo",
        "animalEnclsoure": " North East side of the Zoo. ",
        "animalDescription":" Our lions are our most popular animals and it's easy to see why. They have golden coats, and the males have manes. They also have powerful legs, teeth and jaws which were used to hunt prey in the wild."
    },
    {
        "animalName":"cheetah",
        "animalPic": "images/cheetah",
        "animalSpecies": "A. jubatus",
        "animalEnclsoure": " North East side of the Zoo. Close to the lions ",
        "animalDescription":" Our Cheetahs are native from Africa. They are the fastest land animal and can reach speeds of 80mph. They are known for their spotted coats and black snouts."
    },
    {
        "animalName":"Zebra",
        "animalPic": "images/zebra",
        "animalSpecies": "Equus grevyi,E. quagga,E. zebra",
        "animalEnclsoure": " South West side of the Zoo. Close to the entrance",
        "animalDescription":" Zebras are well known because of their stripes. They are native to Africa. "
    },
    {
        "animalName":"Crocodile",
        "animalPic": "images/crocodile",
        "animalSpecies": "Crocodylidae",
        "animalEnclsoure": " North West side of the Zoo. Opposite the Lions.",
        "animalDescription":" Crocodiles native from the tropics in Africa. They are moree closley rleated to birds and dinosaurs than other reptiles. They hunt mainly at night due to their nocturnal vision. "
    }
]

Here is my animal component:

import React from 'react';
import "../animal.css";

const animal = (props) => {
    return (
        <div className="Animal">
            <h2>{props.animalName}</h2>
            <img className="animalPic" src={props.animalPic} alt={props.aniamlName} />
            <p>Species{props.animalSpecies}</p>
            <p>Enclosure Location{props.animalEnclosure}</p>
            <p>Description:{props.animalDescription}</p>
        </div>

    )
};

export default animal;

Here is my Zoo-Animal component

import React from 'react';
import Animal from './components/Animal';

const zoo = (props) => {
    return (
        <div className="Animal-output">
            {props.animals.map((animal, i) => (
                <Animal key={i} {...animal} />
            ))}
        </div>
    )
};

export default zoo;

Here is my animals page:

import React, {useState, useEffect} from 'react'
import Header from './components/Header';
import "./App.css";
import Animal from'./components/Animal';
import Zoo_Animals from './Zoo_Animals.js'


function Animals(props) {

    const [animals, setAnimals] = useState([]);
    useEffect(() => {
        fetch("./json/animal-list.json").then(function(jresponse) {
            if(jresponse.ok) {
                jresponse.json().then(function(json) {
                    setAnimals(json);
                });
            } else {
                console.log('error' + jresponse.status + ": " + jresponse.text);
            }
        });

    });

    return(
        <div>
            <h1>Animals</h1>
            <Zoo_Animals/>
        </div>
    )
}

export default Animals;
1 Answers

It looks like you're just not passing the animals to the Zoo_Animals component:

<Zoo_Animals/>

Since the component expects that as a prop, pass it:

<Zoo_Animals animals={animals} />

Note also that since the data is by default an empty array:

const [animals, setAnimals] = useState([]);

Then at first there won't be any animals. (Which is very much a good thing and prevents this same error from happening while the AJAX operation is loading.) It will render them when the AJAX operation completes and updates the state.

As a learning exercise, you might also track some kind of "is loading" state value to display a loading indicator to the user while the AJAX operation is occurring.

Related