Home > OS >  Cannot read properties of undefined (reading 'map')
Cannot read properties of undefined (reading 'map')

Time:09-16

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:

Edit cannot-read-properties-of-undefined-reading-map

  • Related