I'm attempting to render a page of Pokemon with their attributes (when selected) in react-redux.
I have a PokemonDetail component
export function pokemonDetail (props) {
const { id } = useParams()
const moves = Object.values(props.state.entities.moves).map((val) => val.name)
const thisPokemon = props.state.entities.pokemon[id]
useEffect(() => {
props.requestSinglePokemon(id)
}, [id])
return(
<section className="pokemon-detail">
<ul>
<figure>
<img src={thisPokemon.imageUrl} alt={thisPokemon.name} />
</figure>
<li><h2>{thisPokemon.name}</h2></li>
<li>Type: {thisPokemon.pokeType}</li>
<li>Attack: {thisPokemon.attack}</li>
<li>Defense: {thisPokemon.defense}</li>
<li>Moves: {moves.join(', ')}</li>
</ul>
</section>
)
}
This component makes a request to grab a Pokemon via a thunk action
export const requestSinglePokemon = (id) => (dispatch) => {
APIUtil.fetchPokemon(id).then(
(payload) => (dispatch(receiveOnePokemon(payload)))
)
}
The problem is, the moves object will be blank {} until the request completes, where it will then be populated with the Pokemon, moves, and items. When it tries to initially render, then, it will throw an error that it's trying methods on a blank object. An easy fix to this is to simply write if (thisPokemon)... { but I'm wondering if there's a way to make my constants wait for the request to complete before being defined.
Without seeing how the props interact with each other or the exact implementation of the
requestSinglePokemon, I can only give you a workaround where you define a local variable that reacts tothisPokemonand use that to conditional render. Basically what you are doing with theif (thisPokemon)code, but easier to readBasically, you could define a loading state and render a loader accordingly to the truthy-iness of
thisPokemon.E.g.
A better solution is to simply modify the parent props and conditional the component as a whole, so the loading logic is done at the container instead of the component. This way, the
PokemonDetailcomponent does not have to care about undefinedthisPokemonconditions.i.e. Do the conditional rendering at the parent component