I need your help. I'm trying to get API data through redux. I have everything I need: action_types, action_creators, reducer. When I try to draw data, I get an error: Cannot read properties of undefined (reading 'map')
.What is my mistake? Thank you very much. Here is my code
cartoons.js
import React, {useEffect} from "react";
import {useDispatch, useSelector} from "react-redux";
import {cartoons_are_loaded} from "../redux/action_creators";
export let Cartoons = () => {
let dispatch = useDispatch();
let cartoons = useSelector(({cartoon_reducer: {cartoons}}) => cartoons);
let fetchCartoons = async () => {
try {
let response = await fetch('https://api.sampleapis.com/cartoons/cartoons2D');
let json = await response.json();
console.log(json);
dispatch(cartoons_are_loaded(json.data))
} catch (e) {
console.log(e)
}
}
useEffect(() => {
if (!cartoons.length){
fetchCartoons();
}
},[])
return (<div>
{cartoons.map(el => <div key={el.id}>{el.title}</div>)}
</div>)
}
reducers.js
import {CARTOONS_ARE_LOADED} from "./action_types";
let initialState = {
cartoons: []
}
let cartoon_reducer = (state = initialState, action) => {
switch (action.type) {
case CARTOONS_ARE_LOADED: {
return {
...state,
cartoons: action.payload
}
}
default:
return state;
}
}
export default cartoon_reducer;
action_types.js
let CARTOONS_ARE_LOADED = 'CARTOONS_ARE_LOADED';
let DELETE_FAVOURITE_MOVIE = 'DELETE_FAVOURITE_MOVIE';
let ADD_FAVOURITE_CARTOON = 'ADD_FAVOURITE_MOVIE';
export {
CARTOONS_ARE_LOADED,
ADD_FAVOURITE_CARTOON,
DELETE_FAVOURITE_MOVIE
}
action_creators.js
import {
CARTOONS_ARE_LOADED,
} from "./action_types";
let cartoons_are_loaded = (payload) => ({type : CARTOONS_ARE_LOADED, payload});
export {
cartoons_are_loaded
}
all_reducers.js
import cartoon_reducer from "./reducers";
import {combineReducers} from "redux";
export let root_reducer = combineReducers({
cartoon_reducer
})
CodePudding user response:
Issue
The JSON response is already an array.
let json = await response.json();
// 20210915235745
// https://api.sampleapis.com/cartoons/cartoons2D
[
{
"title": "Spongebob Squarepants",
"year": 1999,
"creator": [
"Stephen Hillenburg"
],
"rating": "TV-Y",
"genre": [
"Comedy",
"Family"
],
"runtime_in_minutes": 23,
"episodes": 272,
"image": "https://nick.mtvnimages.com/uri/mgid:arc:content:nick.com:9cd2df6e-63c7-43da-8bde-8d77af9169c7?quality=0.7",
"id": 1
},
...
{
"title": "The New Adventures of Winnie the Pooh",
"year": 1988,
"creator": [
"Karl Geurs",
"Terence Harrison",
"Ken Kessel"
],
"rating": "TV-Y",
"genre": [
"Adventure",
"Comedy"
],
"runtime_in_minutes": 30,
"episodes": 50,
"image": "https://m.media-amazon.com/images/M/MV5BZjFkZDkwYjktMmZkNi00ZTVkLWI5ZmItZWI2MmI1NjQ1Y2U0XkEyXkFqcGdeQXVyOTg4MDk3MTQ@._V1_SY1000_CR0,0,666,1000_AL_.jpg",
"id": 23
}
]
There is no data
property, or in other words, json.data
is undefined, and thus, not mappable.
Solution
Just dispatch the action with the json
JSON data value:
dispatch(cartoons_are_loaded(json))
Full code:
const fetchCartoons = async () => {
try {
let response = await fetch('https://api.sampleapis.com/cartoons/cartoons2D');
let json = await response.json();
console.log(json);
dispatch(cartoons_are_loaded(json)) // <-- pass just `json`
} catch (e) {
console.log(e)
}
}
Here's an example codesandbox using local state instead of redux: