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!
CodePudding user response:
It means that characters.results
is not an array.
What does it show when you console.log(characters.results)
?
CodePudding user response:
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>;
})