I'm having an issue with displaying an array of Pokemon moves that I've retrieved from the database (using a rails/react/redux). The strange thing is that when I display the entire array without trying to use join on it, everything's fine. But when I try to use join on it, I get this error message: Uncaught TypeError: Cannot read property 'join' of undefined. And when I display the entire array variable as is, without modifying anything, it does display.
I've gone through my code and I've confirmed that the routing is fine and the right action creators are being dispatched. I've also gone through my reducers and I can confirm that they are using the right action constants to make decisions as to what the new state object is. The only thing that I can think of is that maybe the problem lies in one of these places below:
// the component that renders my Pokemon details onto the page
class PokemonDetail extends React.Component {
componentDidMount() {
this.props.requestSinglePokemon(this.props.match.params.pokemonId);
}
componentDidUpdate(prevProps) {
if (prevProps.match.params.pokemonId !== this.props.match.params.pokemonId) {
this.props.requestSinglePokemon(this.props.match.params.pokemonId);
}
}
render() {
const { pokemon } = this.props;
if (!pokemon) return null;
return (
<section className='pokemon-detail'>
<figure>
<img src={ pokemon.image_url } alt={ pokemon.name } />
</figure>
<ul>
<li><h1>{ pokemon.name }</h1></li>
<li>Type: { pokemon.poke_type }</li>
<li>Attack: { pokemon.attack }</li>
<li>Defense: { pokemon.defense }</li>
<li>Moves: { pokemon.moves.join(', ') }</li>
</ul>
</section>
);
}
}
// the reducer
const pokemonReducer = (state = {}, action) => {
Object.freeze(state);
let poke;
switch(action.type) {
case RECEIVE_ALL_POKEMON:
return Object.assign({}, state, action.pokemon);
case RECEIVE_SINGLE_POKEMON:
poke = action.payload.pokemon;
return Object.assign({}, state, { [poke.id]: poke });
default:
return state;
}
}
// the action creators
export const requestSinglePokemon = id => dispatch => {
dispatch(startLoadingSinglePokemon());
return APIUtil.fetchSinglePokemon(id).then(pokemon => dispatch(receiveSinglePokemon(pokemon)));
}
export const receiveSinglePokemon = payload => ({
type: RECEIVE_SINGLE_POKEMON,
payload
});
// the backend APIUtil method
export const fetchSinglePokemon = id => (
$.ajax({
method: 'GET',
url: `api/pokemon/${id}`
})
);
It's the strangest thing...when I do { JSON.stringify(pokemon.moves) } I can literally see that it is an array of strings (of Pokemon moves). And even when I just display it like this, { pokemon.moves }, it seems to be correctly grabbing the right Pokemon; the name, type, attack, and defense text is all there and the moves is also displayed (although not correctly formatted).
NOTE: Upon observing my log (it shows me the action creators that are dispatched when I interact with the page), the error with join seems to pop up before (or instead?) of the action creator that should have been dispatched (i.e. I see that the START_LOADING_SINGLE_POKEMON action is never dispatched before this error pops up)