Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

how to fix "Cannot read properties of undefined (reading 'front_default') "?

I’m trying to display a piece of data from an API, I can reach it, but its giving me an unknown error I cant find an answer for it.


The error message :

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

now, here’s the funny part, when i first starting the page, its working, but if i refresh it, its giving me the error message on console and a white screen page.

this is the part of my code that don’t seems to work.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

                <img src={urlData.sprites.front_default}></img>

but, similar data can work, such as this line:

                <p> {urlData.id}</p>

I’ll post the all code under here, but don’t waste your time on reading it all, try focus on the error message and error origin in order of helping me identifying the problem.

dad component:

import './App.css';
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import { PokemonContainer } from './components/Pokemon';

function App() {

  const [pokemonData, setPokemonData] = useState([]);
  const [loaded, setLoaded] = useState(false);

  const get_pokemon_data = async () => {
    setPokemonData((await axios.get('https://pokeapi.co/api/v2/pokemon?limit=9')).data.results);
  };

  useEffect(() => {
    get_pokemon_data();
  }, []);

  useEffect(() => {
    setLoaded(true);
  }, [pokemonData]);

  if (loaded) {
    return (
      <div>
        {pokemonData.map((pokemon: any) => (
          <PokemonContainer key={pokemon.name} url={pokemon.url} />
        ))}
      </div>
    );
  } else {
    return (
      <div>
        <p>wait a minute</p>
      </div>
    )
  }


};

export default App;

child component :

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


export const PokemonContainer = (props: any) => {
    const [urlData, setURLData] = useState<any>([]);

    const [loaded, setLoaded] = useState<boolean>(false);



    useEffect(() => {
        const get_url_data = async () => {
            setURLData((await axios.get(props.url)).data);
        };
        get_url_data();
    }, []);

    useEffect(() => {
        setLoaded(true);
    }, [urlData]);

    if (loaded) {
        return (
            <div>
                <div key={urlData.name}>
                    <p> {urlData.name}</p>
                    <p> {urlData.id}</p>
                    <img src={urlData.sprites.front_default}></img>
                </div>
            </div>
        )
    } else {
        return (
            <div>
                <p>Loading...</p>
            </div>
        )
    }
};

>Solution :

I think the problem is with your second useEffect

    useEffect(() => {
        setLoaded(true);
    }, [urlData]);

When component mounts this will set loaded to true but response is not fetched yet and urlData is still an empty array (which should be an empty object, I believe) therefore you get the error.

One way to fix this would be to check if urlData has been fetched inside the useEffect? if yes, then set loaded to true.

But I think this useEffecte is not needed at all. Instead of if(loaded) you could check for one urlData‘s properties, like: if(urlData.id)

child component:

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


export const PokemonContainer = (props: any) => {
    const [urlData, setURLData] = useState<any>([]);

    useEffect(() => {
        const get_url_data = async () => {
            setURLData((await axios.get(props.url)).data);
        };
        get_url_data();
    }, []);

    if (urlData.id) {
        return (
            <div>
                <div key={urlData.name}>
                    <p> {urlData.name}</p>
                    <p> {urlData.id}</p>
                    <img src={urlData.sprites.front_default}></img>
                </div>
            </div>
        )
    } else {
        return (
            <div>
                <p>Loading...</p>
            </div>
        )
    }
};

Or you can do it like:

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

export const PokemonContainer = (props: any) => {
  const [urlData, setURLData] = useState<any>([]);

  useEffect(() => {
    const get_url_data = async () => {
      setURLData((await axios.get(props.url)).data);
    };
    get_url_data();
  }, []);

  if (!urlData.id) {
    return (
      <div>
        <p>Loading...</p>
      </div>
    );
  }

  return (
    <div>
      <div key={urlData.name}>
        <p> {urlData.name}</p>
        <p> {urlData.id}</p>
        <img src={urlData.sprites.front_default}></img>
      </div>
    </div>
  );
};
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading