jgcarrillo
jgcarrillo

Reputation: 186

Cannot render data from API being passed from parent to child (ReactJS)

I just tried to follow this question with no results for me.

The point is that I'm trying to get a selected pokemon from a component and pass down to another component. The data is correctly passed, some data are displayed, but with other (for example, the sprites) I got an error. I'm using Context by the way.

PokemonContext.js

import React, { useState } from 'react';

const Context = React.createContext({});

export function PokemonsContextProvider({ children }) {
  const [favorites, setFavorites] = useState([]);

  return <Context.Provider value={{ favorites, setFavorites }}>{children}</Context.Provider>;
}

export default Context;

App.js

<PokemonsContextProvider>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/pokemons" element={<PokemonsList />} />
    <Route path="/favorites" element={<Favorite />} />
    <Route path="/pokemon/:name" element={<PokemonDetails />} />
    <Route path="*" element={<NotFound />} />
  </Routes>
</PokemonsContextProvider>

PokemonsDetails.js

const PokemonDetails = () => {
  const { name } = useParams();
  const [pokemon, setPokemon] = useState('');

  useEffect(() => {
    pokemonService.pokemonDetail(name).then((res) => {
      setPokemon(res);
    });
  }, []);

  return (
    <div>
      <h1 className="text-center mb-4">Details for {name.toUpperCase()}</h1>

      <PokemonCard pokemon={pokemon} />

      <div className="text-center">
        <Link className="btn btn-success mx-2 my-4" to="/favorites">
          Go back
        </Link>
      </div>
    </div>
  );
};

PokemonCard.js

const PokemonCard = ({ pokemon }) => {
  return (
    <div className="card text-center bg-primary">
      <div className="card-body">
        <h5 className="card-title">{pokemon.name}</h5>
      </div>
      <ul className="list-group list-group-flush">
        <li className="list-group-item">Weight: {pokemon.weight}</li>
        <li className="list-group-item">Height: {pokemon.height}</li>
      </ul>
    </div>
  );
};

export default PokemonCard;

When I add this line <img className="card-img-top" src={pokemon.sprites.front_default} alt="Card image cap" /> to the PokemonCard component I got this error:

enter image description here

The data is correctly displayed when I console log it, so, I don't know why I'm having this error. If I inspect the React Dev Tools the data is in the component!

enter image description here

Upvotes: 0

Views: 40

Answers (1)

erduoliveira
erduoliveira

Reputation: 86

The PokemonCard.js component is being rendered before the result of the request.

You can resolve this problem checking if there is a pokemon before use his props.

const PokemonCard = ({ pokemon }) => {
  return pokemon && (
    <div className="card text-center bg-primary">
      <img className="card-img-top" src={pokemon.sprites?.front_default} alt="Card image cap" />
      <div className="card-body">
        <h5 className="card-title">{pokemon.name}</h5>
      </div>
      <ul className="list-group list-group-flush">
        <li className="list-group-item">Weight: {pokemon.weight}</li>
        <li className="list-group-item">Height: {pokemon.height}</li>
      </ul>
    </div>
  );
};

export default PokemonCard;

Upvotes: 2

Related Questions