Home > Enterprise >  React - Uncaught TypeError: Cannot read properties of undefined
React - Uncaught TypeError: Cannot read properties of undefined

Time:09-27

I recently dove back into React after some months, and have been working on a Pokedex side project to familiarize myself again with the framework. I have been met with this message from React reading an undefined property from an API call. I have been able to access the other JSON data fine, but for some reason, when it comes to trying to pull one of the nested properties from "sprites", I receive the following:

Uncaught TypeError: Cannot read properties of undefined (reading 'front_default')
    at PokemonPage (PokemonPage.js:30:1)
    at renderWithHooks (react-dom.development.js:16305:1)
    at mountIndeterminateComponent (react-dom.development.js:20074:1)
    at beginWork (react-dom.development.js:21587:1)
    at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
    at invokeGuardedCallback (react-dom.development.js:4277:1)
    at beginWork$1 (react-dom.development.js:27451:1)
    at performUnitOfWork (react-dom.development.js:26557:1)
    at workLoopSync (react-dom.development.js:26466:1)

I have been able to access this same information with no problem in another component, so not sure where I am going wrong. I spent some time googling possible solutions, but no luck yet with a resolution.

Any tips would be appreciated!

Code I am working with:

const PokemonPage = () => {

    const { id } = useParams();

    const [pokemonDetails, setPokemonDetails] = useState([]);


    useEffect(() => {
      axios({
        method: 'GET',
        url: `https://pokeapi.co/api/v2/pokemon/${id}`,
        params: {id: id}
      }).then(res => {
        console.log(res.data)
        setPokemonDetails(res.data)
      })
    }, []);

  return (
    <div>
          <Card.Title style={{fontSize: '15px'}}>#{pokemonDetails.id} {pokemonDetails.name}</Card.Title>
          <Card.Title style={{fontSize: '15px'}}>{pokemonDetails.base_experience}</Card.Title>
          <Card.Img variant="top" src={pokemonDetails.sprites.front_default} style={{width: '120px'}} />
  </div>
  )
}

Example

Try to render when the pokemonDetails exists. As it not receives an array(receives an object) from response data, you can initialize it as null or undefined to make more sense than an array.

The example below will render pokemonDetails content only when it has data.

const PokemonPage = () => {

    const { id } = useParams();

    const [pokemonDetails, setPokemonDetails] = useState(null);


    useEffect(() => {
      axios({
        method: 'GET',
        url: `https://pokeapi.co/api/v2/pokemon/${id}`,
        params: {id: id}
      }).then(res => {
        console.log(res.data)
        setPokemonDetails(res.data)
      })
    }, []);

  return (
    <div>
          {pokemonDetails ? (<Card.Title style={{fontSize: '15px'}}>#{pokemonDetails.id} {pokemonDetails.name}</Card.Title>
          <Card.Title style={{fontSize: '15px'}}>{pokemonDetails.base_experience}</Card.Title>
          <Card.Img variant="top" src={pokemonDetails.sprites.front_default} style={{width: '120px'}} />) : <div>loading...</div>}
    </div>
  )
}

CodePudding user response:

because, when component will mount your state equal empty array. So, [].sprites equal undefined and undefined.front_default you catch error with Cannot read properties of undefined

You can change your code to this

<Card.Img variant="top" src={pokemonDetails?.sprites?.front_default} style={{width: '120px'}} />
  • Related