API response mapping shows Cannot read properties of undefined (reading 'map')

When I make an API call and store the response in useState, it shows the data while running console.log(), however when this state value is passed as an argument to another component which is supposed to take the data and mapped it to show the result, it gives me an error saying
" Cannot read properties of undefined (reading ‘map’)"

The data shows output result console.log() of
Product.jsx whereas it shows undefined in MenShoes.jsx and WomenShoes.jsx

Can anyone help me figure out what’s wrong with my code?

enter image description here

Here’s my code for Product.jsx

import { useMediaQuery } from '@mui/material';
import { Box } from '@mui/system';
import React from 'react'
import { theme } from '../style/theme';
import MenShoes from './collections/MenShoes';
import WomenShoes from './collections/WomenShoes';
export const Products = () => {

    const matchScreen = useMediaQuery(theme.breakpoints.down('md'))
    const [isLoading, setIsLoading] = React.useState(true);
    const [menFootwears, setMenFootwears] = React.useState([]);
    const [womenFootwears, setWomenFootwears] = React.useState([]);
 

    //Women FootWears
    async function fetchWomenFootwear () {
        setIsLoading(true)
        await fetch('https://dummyjson.com/products/category/womens-shoes')
            .then(response => response.json())
            .then(response => setWomenFootwears(response.products)) 
        setIsLoading(false);     
    }
    //Men Footwears
    async function fetchMenFootwear () {
        setIsLoading(true)
        await fetch('https://dummyjson.com/products/category/mens-shoes')
            .then(response => response.json())
            .then(response => setMenFootwears(response.products))
        setIsLoading(false)
        
    }
  
    React.useEffect(()=> {
        fetchWomenFootwear()
        fetchMenFootwear()
    }, [])

    const handleProductCard = (id) => {
        console.log('hello')
    } 
    
    console.log( womenFootwears, menFootwears)

  return (
    <Box>
       <WomenShoes data={womenFootwears} onclick={handleProductCard} loadingStatus={isLoading}/>
       <MenShoes data={menFootwears} onclick={handleProductCard} loadingStatus={isLoading}/>
    </Box>
  )
}

Both WomenShoes and MenShoes are designed using the same code except for the API response array data.

MenShoes/WomenShoes.jsx

import { ShoppingCartSharp } from '@mui/icons-material';
import { Button, Card, CardActionArea, CardContent, CardMedia, Divider, Rating, Skeleton, Typography, useMediaQuery } from '@mui/material';
import { Box } from '@mui/system';
import React from 'react'
import { theme } from '../../style/theme';


export default function MenShoes({menFootwears, handleProductCard, isLoading}) {

    const matchScreen = useMediaQuery(theme.breakpoints.down('md'))
    
    return(
        <Box pt={2} mt={4}>  
            <Divider variant='middle' sx={{
                "&.MuiDivider-root": {
                    "&::before, &::after": {
                        borderTopColor:theme.palette.primary.light,
                        borderTopWidth:'thin',
                        borderTopStyle:'solid'
                    },
                }
            }}>
                <Typography color={theme.palette.primary.main} variant={!matchScreen ? 'h3': 'h5'}>
                    Men Footwears Collections
                </Typography>
            </Divider>
            <Box display='flex' 
            justifyContent='space-evenly' 
            alignItems='center'
            flexWrap='wrap'
            pt={2}
            mt={2}
            px={2}>
                {menFootwears && menFootwears.map((menFootwear)=> (
                <Card key={menFootwear.id}
                        sx={{maxWidth:335,
                        height:'auto',
                        marginTop:'3.5em',
                        flex:!matchScreen ? '0 0 45%' : '0 0 80%' 
                        }}
                        elevation={4}
                        onClick={()=>{handleProductCard(menFootwear.id)}}>
                    <CardActionArea>
                        {isLoading ? 
                        <>
                            <Skeleton variant='rectangular' width='335' height='220' animation='wave'/>
                        </> :
                            <CardMedia component='img'
                                height='220'
                                image={menFootwear.images[0]}/>}
                        <CardContent sx={{
                            textAlign:'center',
                        }}>
                            { isLoading ? 
                            <>
                                <Skeleton variant='h6' animation='wave'/>
                            </> :
                            <Typography gutterBottom variant='h6'
                            fontWeight='bold' 
                            color={theme.palette.primary.main}>
                                {menFootwear.title}
                            </Typography>}

                            {isLoading ? 
                            <>
                                <Skeleton variant='body2' animation='wave'/>
                            </> :
                            <Typography variant='body2' gutterBottom color={theme.palette.primary.dark}>
                                Brand : {menFootwear.brand}
                            </Typography>}

                            { isLoading ? 
                            <>
                                <Skeleton variant='h5' animation='wave'/>
                            </> :
                            <Typography variant='h5' gutterBottom color={theme.palette.primary.main}>
                                $ {menFootwear.price}
                            </Typography>}
                            <Rating
                            size='small'
                            name="rating"
                            value={menFootwear.rating}
                            readOnly/>
                        </CardContent>
                    </CardActionArea>
                        { isLoading ? 
                            <>
                                <Skeleton variant='rectangular' width='335' height='20' animation='wave'/>
                            </> :
                        <Button size='medium' 
                        sx={{all:'unset',
                            textAlign:'center',
                            fontFamily:theme.typography.fontFamily,
                            fontSize:16,
                            width:'100%',
                            padding:'0.7em',
                            margin:0,
                            color:'white',
                            background:`linear-gradient(90deg, ${theme.palette.primary.main},transparent) ${theme.palette.tertiary.main}`,
                            transition:'background 0.5s',
                            '&:hover': {
                                background:theme.palette.secondary.main,
                            }
                            }}>
                            <span  style={{display:'inline-flex', alignItems:'center'}}>
                                    <ShoppingCartSharp size='small'/>&nbsp;&nbsp;Add to Cart 
                            </span> 
                        </Button>}
                </Card>
            ))}
            </Box>
        </Box>
    )
}

Hello!

In your footwear component, you’re passing the props data, onclick and loadingStatus, but your component is expecting menFootwears, handleProductCard, isLoading, that’s why it is undefined.

Instead of deconstructing the props parameter, log it to see what I mean (or use react developer tools to see the props passed to the component)

Thank you. It’s working now. Initially, I thought if we use curly brackets, we can add the original variable name.

1 Like

Yes, when you use curly brackets (which is called destructuring assignment) you can “rename” a property of an object, like this:

function myFunction({ originalName: theNewName, doesNotExist }) {
  console.log(theNewName); // Output: This is the value
  console.log(doesNotExist); // Output: undefined
}

const param = {
  originalName: 'This is the value'
};

myFunction(param);
1 Like

I see! Thank you for the explanation

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.