Home > Net >  React : Uncaught TypeError: items.map is not a function
React : Uncaught TypeError: items.map is not a function

Time:10-05

When I click the certain button to redirect to the page, the page did not show the content.

When I checked View => Developer => Developer Tools => console, it shows errors text below:

Uncaught TypeError: items.map is not a function at ShoppingCart.js:6:1

at mountMemo (react-dom.development.js:15846:1)

at Object.useMemo (react-dom.development.js:16219:1)

at useMemo (react.development.js:1532:1)

at ShoppingCart (ShoppingCart.js:6:1)

at renderWithHooks (react-dom.development.js:14985:1)

at mountIndeterminateComponent (react-dom.development.js:17811:1)

at beginWork (react-dom.development.js:19049:1)

at HTMLUnknownElement.callCallback (react-dom.development.js:3945:1)

at Object.invokeGuardedCallbackDev (react-dom.development.js:3994:1)

The above error occurred in the component:

at ShoppingCart (http://localhost:3000/static/js/bundle.js:1063:68)
at div
at http://localhost:3000/static/js/bundle.js:20449:23
at div
at http://localhost:3000/static/js/bundle.js:23024:23
at div
at http://localhost:3000/static/js/bundle.js:20648:23
at Menu (http://localhost:3000/static/js/bundle.js:2709:76)
at Route (http://localhost:3000/static/js/bundle.js:184334:29)
at Switch (http://localhost:3000/static/js/bundle.js:184536:29)
at Router (http://localhost:3000/static/js/bundle.js:183969:30)
at BrowserRouter (http://localhost:3000/static/js/bundle.js:183590:35)
at AuthProvider (http://localhost:3000/static/js/bundle.js:1962:5)
at App

Consider adding an error boundary to your tree to customize error handling behavior. Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.

Errors messages in Developer Tools

Error message in Developer Tools 1

rror message in Developer Tools 1

import { IoCloseOutline } from 'react-icons/io5';
import { useParams } from 'react-router-dom';
import React, { useState, useEffect, useMemo } from 'react';
import { fetchPlace } from '../apis';
import styled from 'styled-components';

import MenuList from '../components/MenuList';
import ShoppingCart from '../components/ShoppingCart';

const OrderButton = styled(Button)`
    position: fixed;
    bottom: 20px;
    right: 20px;
    border-radius: 50%;
    box-shadow: 1px 1px 8px rgba(0,0,0,0.2);
    width: 60px;
    height: 60px;
`;

const Menu = () => {
    const [place, setPlace] = useState({});
    const [shoppingCart, setShoppingCart] = useState({});
    const [showShoppingCart, setShowShoppingCart] = useState(false);

    const params = useParams();

    const onFetchPlace = async () => {
        const json = await fetchPlace(params.id);
        console.log(json);
        if (json) {
            setPlace(json);
        }
    };

    const onAddItemtoShoppingCart = (item) => {
        setShoppingCart({
            ...shoppingCart,
            [item.id]: {
                ...item,
                quantity: (shoppingCart[item.id]?.quantity || 0)   1,
            }
        });
    }

    const onRemoveItemToShoppingCart = (item) => {
        if (totalQuantity === 1) {
            setShowShoppingCart(false);
        }

        setShoppingCart({
            ...shoppingCart,
            [item.id]: {
                ...item,
                quantity: (shoppingCart[item.id]?.quantity || 0) - 1,
            }
        });
    }

    const totalQuantity= useMemo(
        () => Object.keys(shoppingCart)
                .map((i) => shoppingCart[i].quantity)
                .reduce((a,b) => a   b, 0),
            [shoppingCart] 
    );

    useEffect(() => {
        onFetchPlace();
    }, []);

    return (
        <Container className="mt-5 mb-5">
            <Row className="justify-content-center">
                <Col lg={8}>
                    {showShoppingCart ? (
                        <ShoppingCart 
                            items={Object.keys(shoppingCart)
                                .map((key) => shoppingCart[key])
                                .filter((item) => item.quantity > 0)
                            }
                            onAdd={onAddItemtoShoppingCart}
                            onRemove={onRemoveItemToShoppingCart}
                        />
                    ) : (
                        <MenuList 
                            place={place} 
                            shoppingCart={shoppingCart} 
                            onOrder={onAddItemtoShoppingCart} 
                        />
                    )}
                    
                </Col>
            </Row>

            {totalQuantity ? (
                <OrderButton variant="standard" onClick={() => setShowShoppingCart(!showShoppingCart)}>
                    {showShoppingCart ? <IoCloseOutline size={25} /> : totalQuantity}
                </OrderButton>
            ) : null}
        </Container>
    )
};

export default Menu;

Shopping Cart Code(Where the errors happened)

import { Card } from 'react-bootstrap';
import OperationButton from './OperationButton';

const ShoppingCart = ( items, onAdd, onRemove ) => {
    const totalPrice = useMemo(
        () => items.map((i) => i.quantity * i.price).reduce((a,b) => a   b, 0),
        [items]
    );

    return (
        <>
            <h3 className="text-center mb-4">
                <b>Your Order</b>
            </h3>
            <Card>
                <Card.Body>
                    {items.map((item) => (
                        <div key={item.id} className="d-flex mb-4 align-items-center">
                            <div className="flex-grow-1">
                                <p className="mb-0">
                                    <b>{item.name}</b>
                                </p>
                                <span>${item.price}</span>
                            </div>

                            <div className="d-flex align-items-center">
                                <OperationButton
                                    variant="lightgray"
                                    size="sm"
                                    onClick={() => onRemove(item)}

                                >    
                                    -
                                </OperationButton>
                                <span>{item.quantity}</span>
                                <OperationButton
                                    variant="lightgray"
                                    size="sm"
                                    onClick={() => onAdd(item)}
                                    
                                >    
                                     
                                </OperationButton>
                            </div>
                        </div>
                    ))}

                    <hr/>
                    <div className="d-flex justify-content-between">
                        <h5><b>Total</b></h5>
                        <h5><b>{totalPrice}</b></h5>
                    </div>
                </Card.Body>
            </Card>
        </>
    );
};

export default ShoppingCart;

My package.json

  "version": "0.1.0",
  "private": true,
  "proxy": "http://localhost:8000",
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "bootstrap": "^4.6.0",
    "qrcode.react": "^3.1.0",
    "react": "^17.0.2",
    "react-bootstrap": "^1.5.2",
    "react-dom": "^17.0.2",
    "react-dropzone": "^11.3.2",
    "react-icons": "^4.2.0",
    "react-router-dom": "^5.2.0",
    "react-scripts": "^5.0.1",
    "react-to-print": "^2.14.7",
    "react-toastify": "^7.0.3",
    "styled-components": "^5.2.3",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

This is the page This is the page

In this page, after I click the "Add to shopping cart" button, one order button will be appeared at the right bottom of the page. After that, when I click the order button it will direct to a page and supposed it will shows like that.

After click order button(Not mine

However, for mine, it shows nothing. My page after click order button

Can anyone tell me how to resolve it?

CodePudding user response:

const ShoppingCart = ( items, onAdd, onRemove ) => { is not how you access the prop values. The component has one argument (props) not three arguments.

So you have just named props items which is an object, objects don't have map on them like arrays. Next time add a console log in to see what items is.

What you meant to do is destructure the props object:

const ShoppingCart = ({ items, onAdd, onRemove }) => {

CodePudding user response:

Your ShoppingCart component declaration is not right. Function components receive one argument only, the props object.

You can destruct the prop argument like this:

const ShoppingCart = ({ items, onAdd, onRemove }) => {
//...

CodePudding user response:

sorry, haven't read the full question. but you should always check if the array has length or not (which means it has some value or not).

items?.length && items.map()

items?.length will make sure if the array exists and has some length.

also you can use something like:

items?.length ? items.map() : 'no data found'
  • Related