javascriptreactjsarraysstrapi

Uncaught TypeError: Cannot read properties of undefined (reading 'data') at Category i am getting this error please help me to solve it


when i do not map any data in Category.jsx it works fine as soon as i try to grab data from strapi api and write following code in Category.jsx i got UncoughtTypeError in my consol.

Home.jsx

import { useEffect, useContext } from "react";

import "./Home.scss";

import Banner from './Banner/Banner'
import Category from "./Category/Category";
import Products from "../Products/Products";
import { fetchDataFromApi } from "../../utils/api";
import { Context } from "../../utils/context";

const Home = () => {
    const { categories, setCategories, products, setProducts } = useContext(Context);
    useEffect(() => {
        getProducts();
        getCategories();
    }, []);

    const getProducts = () => {
        fetchDataFromApi("/api/products?populate=*").then(res => {
            console.log(res)
            setProducts(res)
        });
    }

    const getCategories = () => {
        fetchDataFromApi("/api/categories?populate=*").then(res => {
            console.log(res)
            setCategories(res)
        });
    }

    return (
        <div>
            <Banner />
            <div className="main-content">
                <div className="layout">
                    <Category categories={categories} />
                    <Products products={products} headingText="Popular Products" />
                </div>
            </div>
        </div>
    );
};

export default Home;

Category.jsx

import "./Category.scss";

import cat1 from '../../../assets/category/cat1.jpg'

const Category = ({categories}) => {
    return (
        <div className="shop-by-category">
            <div className="categories">
                {categories.data.map((item) => {
                    <div key={item.id} className="category">
                        <img src={process.env.REACT_APP_STORE_URL + item.attributes.img.data.attributes.url} 
                        alt="" />
                    </div> 
                })}        
            </div>
        </div>
    );
};

export default Category;

context.jsx

import { createContext, useState } from "react";

export const Context = createContext();

const AppContext = ({ children }) => {
    const [categories, setCategories] = useState()
    const [products, setProducts] = useState()
    return (
        <Context.Provider
            value={{
                categories,
                setCategories,
                products,
                setProducts
            }}>
            {children}
        </Context.Provider>
    );
}

export default AppContext;

api.js

import axios from "axios";

const params = {
    headers: {
        Authorization: "bearer" + process.env.REACT_APP_STRIPE_APP_KEY
    }
}

export const fetchDataFromApi = async (url) => {
    try {
        const { data } = await axios.get(process.env.REACT_APP_STORE_URL + url, params)
        return data
    } catch (error) {
        console.log(error)
        return error
    }
}

As this is my first project i am not very comfortable with it, looking for easy and better solution


Solution

  • You can check the value of categories.data before map. And conditionally display a failure message.

    Also included return ( ... ) inside your loop

    const Category = ({categories}) => {
      return (
        <div className="shop-by-category">
          <div className="categories">
            {
              categories && categories.data ? 
              categories.data.map((item) => { 
                return (
                  <div key={item.id} className="category">
                    {item.id}
                    <img src={process.env.REACT_APP_STORE_URL + item.attributes.img.data.attributes.url} alt="" />
                  </div>
                )
              }) : (
                <div>No categories</div>
              )
            }
          </div>
        </div>
      )
    };