I have the following code: characterActions.js
export const getCharacters = () => async(dispatch) => {
try {
dispatch({ type: FETCH_CHARACTERS_REQUEST })
const { data } = await axios.get('https://rickandmortyapi.com/api/character')
dispatch({
type: FETCH_CHARACTERS_SUCCESS,
payload: data
})
} catch (error) {
dispatch({
type: FETCH_CHARACTERS_FAIL,
payload: 'error'
})
}
}
characterReducers.js
import {
FETCH_CHARACTERS_REQUEST,
FETCH_CHARACTERS_SUCCESS,
FETCH_CHARACTERS_FAIL,
} from '../actions/characters/characterConstants'
export const characterListReducer = (state = { characters: {} }, action) => {
switch(action.type) {
case FETCH_CHARACTERS_REQUEST:
return { loading: true, characters: [] }
case FETCH_CHARACTERS_SUCCESS:
return { loading: false, characters: action.payload }
case FETCH_CHARACTERS_FAIL:
return { loading: false, error: action.payload }
default:
return state;
}
}
and HomeScreen.js where I want to display the fetched characters
const HomeScreen = () => {
const dispatch = useDispatch()
const charactersList = useSelector(state => state.charactersList)
const { loading, error, characters } = charactersList
console.log(characters.results)
useEffect(() => {
dispatch(getCharacters())
}, [dispatch])
return (
<div>
{characters.results.map((character) => {
<h1 key={character.id}>{character.name}</h1>
})}
</div>
)
}
When go into the browser i keep getting ** TypeError: Cannot read properties of undefined (reading 'map') **
I am trying to fetch data from Rick and Morty API.
Thank you guys!
It means that characters.results is not an array.
What does it show when you console.log(characters.results)?
It may possibly be in error characters should be an empty array. For safe, you can either use ||[] or simply return a blank array.
export const characterListReducer = (state = { characters: {} }, action) => {
switch(action.type) {
case FETCH_CHARACTERS_REQUEST:
return { loading: true, characters: [] }
case FETCH_CHARACTERS_SUCCESS:
return { loading: false, characters: action.payload || [] } // here, in case null data.
case FETCH_CHARACTERS_FAIL:
return { loading: false, error: action.payload, characters:[] } // here, on error
default:
return state;
}
}
Add check before looping in case of error
const HomeScreen = () => {
const dispatch = useDispatch();
const charactersList = useSelector((state) => state.charactersList);
const { loading, error, characters } = charactersList;
useEffect(() => {
dispatch(getCharacters());
}, [dispatch]);
return (
<div>
{loading ? (
<p>Loading please wait...</p>
) : error ? (
<strong>There is error while fetching data, {error}</strong>
) : (
characters.results.map((character) => {
<h1 key={character.id}>{character.name}</h1>;
})
)}
</div>
);
};
/// Updated code:
const { data } = await axios.get('https://rickandmortyapi.com/api/character')
dispatch({
type: FETCH_CHARACTERS_SUCCESS,
payload: data.results // use results instead to make it consistent with above assign
})
/// Home screen
// remove results now
characters.map((character) => {
<h1 key={character.id}>{character.name}</h1>;
})