Home > Back-end >  Too slow data fetching in React, leading to annot read properties of undefined error
Too slow data fetching in React, leading to annot read properties of undefined error

Time:01-30

I have a problem with data displaying. Probably the JSX content is rendering too fast before data is actually fetched from API and that causing the following:

Uncaught TypeError: Cannot read properties of undefined (reading 'name')

I checked with console.log; sometimes it's fetching, sometimes not. Also, when I comment out this {concerts[1].name}, then data is loaded and populated. However, when I run it like in the example below, data is not populating, and I am getting errors.

import React from "react";
import { useEffect, useState } from "react";
import axios from "axios";

export const ConcertNewest = () => {
  const [concerts, setConcerts] = useState([]);

  useEffect(() => {
    const loadConcerts = async () => {
      const response = await axios.get("/data/concerts");

      setConcerts(response.data);
    };
    loadConcerts();
  }, []);

  console.log("concerts: "   concerts.length);
  return (
    <show>
      <h1>Newest concerts </h1>
      <div>
        <div className="card">
          <img src="" style={{ width: 100 }} />
          <div className="card-text">
            <h4> {concerts[1].name}</h4>
          </div>
        </div>
      </div>
    </show>
  );
};

CodePudding user response:

The code inside useEffect runs after the JSX is rendered. That's by design. So you are ending up with concerts[1].name while concerts is still empty.

A common way to tackle this is to show some loading indicator while the data is being fetched, like so, for example:

import React from "react";
import { useEffect, useState } from "react";
import axios from "axios";

export const ConcertNewest = () => {
  const [concerts, setConcerts] = useState([]);

  useEffect(() => {
    const loadConcerts = async () => {
      const response = await axios.get("/data/concerts");

      setConcerts(response.data);
    };
    loadConcerts();
  }, []);

  if (!concerts.length) {
    return <p>Loading...</p>;
  }
  return (
    <show>
      <h1>Newest concerts </h1>
      <div>
        <div className="card">
          <img src="" style={{ width: 100 }} />
          <div className="card-text">
            <h4> {concerts[1].name}</h4>
          </div>
        </div>
      </div>
    </show>
  );
};
  • Related