admin管理员组

文章数量:1287126

When Accessing the line_items array of the cart object in merce js, i get an error saying that it is undefined, while I can still see it in the console.

Here is some screenshots:

Error:

TypeError: Cannot read property 'length' of undefined
Cart
D:/Zayeed/Projects/e_merce/src/ponents/Cart/Cart.jsx:7
   4 | 
   5 | const Cart = ({ cart }) => {
   6 |     const classes = useStyles();
>  7 |     const isEmpty = !cart.line_items.length;
   8 | 
   9 |     const EmptyCart = () => (
  10 |         <Typography variant="subtitle1">You have no items in your cart, start adding some.</Typography

My Code:

import React from 'react'
import { Container, Typography, Button, Grid } from '@material-ui/core'
import useStyles from './styles';

const Cart = ({ cart }) => {
    const classes = useStyles();
    const isEmpty = !cart.line_items.length;

    const EmptyCart = () => (
        <Typography variant="subtitle1">You have no items in your cart, start adding some.</Typography>
    );

    const FilledCart = () => {
        <>
            <Grid container spacing={3}>
                {cart.line_items.map(item => (
                    <Grid item xs={12} sm={4} key={item.id}>
                        <div>{item.name}</div>
                    </Grid>
                ))}
            </Grid>

            <div className={classes.cardDetails}>
                    <Typography variant="h4">Subtotal: {cart.subtotal.formatted_with_symbol}</Typography>
                    <div>
                        <Button className={classes.emptyButton} size="large" type="button" variant="contained" color="secondary">Empty Cart</Button>
                        <Button className={classes.checkout} size="large" type="button" variant="contained" color="primary">Checkout</Button>
                    </div>
            </div>
        </>
    }

    return (
        <Container>
            <div className={classes.toolbar}/>
            <Typography className={classes.title} variant="h3">Your Shopping Cart:</Typography>
            {isEmpty ? <EmptyCart/> : <FilledCart />}
        </Container>
    )
}

export default Cart

Console Log of the cart object:

App.js:

import React, { useState, useEffect } from 'react'
import { merce } from './lib/merce'
import { Products, Navbar, Cart } from './ponents'

const App = () => {
    const [ products, setProducts ] = useState([])
    const [cart, setCart] = useState({})

    const fetchProducts = async() => {
        const { data } = await merce.products.list()

        setProducts(data)
    }

    const fetchCart = async() => {
        setCart(await merce.cart.retrieve())
    }

    const handleAddToCart = async(productId, quantity) => {
        const item = await merce.cart.add(productId, quantity)

        setCart(item.cart)
    }

    useEffect(() => {
        fetchProducts()
        fetchCart()
    }, []);

    return (
        <div>
            <Navbar  totalItems={cart.total_items}/>
            {/* <Products products={products} onAddToCart={handleAddToCart}/> */}
            <Cart cart={cart}/>
        </div>
    )   
}

export default App

It seems like the prop isn't imported as it is supposed to be, I can't access any property of cart object.

Thanks in advance!

When Accessing the line_items array of the cart object in merce js, i get an error saying that it is undefined, while I can still see it in the console.

Here is some screenshots:

Error:

TypeError: Cannot read property 'length' of undefined
Cart
D:/Zayeed/Projects/e_merce/src/ponents/Cart/Cart.jsx:7
   4 | 
   5 | const Cart = ({ cart }) => {
   6 |     const classes = useStyles();
>  7 |     const isEmpty = !cart.line_items.length;
   8 | 
   9 |     const EmptyCart = () => (
  10 |         <Typography variant="subtitle1">You have no items in your cart, start adding some.</Typography

My Code:

import React from 'react'
import { Container, Typography, Button, Grid } from '@material-ui/core'
import useStyles from './styles';

const Cart = ({ cart }) => {
    const classes = useStyles();
    const isEmpty = !cart.line_items.length;

    const EmptyCart = () => (
        <Typography variant="subtitle1">You have no items in your cart, start adding some.</Typography>
    );

    const FilledCart = () => {
        <>
            <Grid container spacing={3}>
                {cart.line_items.map(item => (
                    <Grid item xs={12} sm={4} key={item.id}>
                        <div>{item.name}</div>
                    </Grid>
                ))}
            </Grid>

            <div className={classes.cardDetails}>
                    <Typography variant="h4">Subtotal: {cart.subtotal.formatted_with_symbol}</Typography>
                    <div>
                        <Button className={classes.emptyButton} size="large" type="button" variant="contained" color="secondary">Empty Cart</Button>
                        <Button className={classes.checkout} size="large" type="button" variant="contained" color="primary">Checkout</Button>
                    </div>
            </div>
        </>
    }

    return (
        <Container>
            <div className={classes.toolbar}/>
            <Typography className={classes.title} variant="h3">Your Shopping Cart:</Typography>
            {isEmpty ? <EmptyCart/> : <FilledCart />}
        </Container>
    )
}

export default Cart

Console Log of the cart object:

App.js:

import React, { useState, useEffect } from 'react'
import { merce } from './lib/merce'
import { Products, Navbar, Cart } from './ponents'

const App = () => {
    const [ products, setProducts ] = useState([])
    const [cart, setCart] = useState({})

    const fetchProducts = async() => {
        const { data } = await merce.products.list()

        setProducts(data)
    }

    const fetchCart = async() => {
        setCart(await merce.cart.retrieve())
    }

    const handleAddToCart = async(productId, quantity) => {
        const item = await merce.cart.add(productId, quantity)

        setCart(item.cart)
    }

    useEffect(() => {
        fetchProducts()
        fetchCart()
    }, []);

    return (
        <div>
            <Navbar  totalItems={cart.total_items}/>
            {/* <Products products={products} onAddToCart={handleAddToCart}/> */}
            <Cart cart={cart}/>
        </div>
    )   
}

export default App

It seems like the prop isn't imported as it is supposed to be, I can't access any property of cart object.

Thanks in advance!

Share Improve this question asked Dec 23, 2020 at 9:58 zayeedBSzayeedBS 757 bronze badges 1
  • Cart ponent will be called at first render with cart={}, while accessing cart.line_items returns 'undefined'. You have to check whether cart.line_items is not undefined and then have to check its length – Vivek Commented Dec 23, 2020 at 10:14
Add a ment  | 

4 Answers 4

Reset to default 6

This is happens because cart content doesnt load from e-merce api immediately when page open and then because of the error it stuck like that.

You can first check is there a cart content first, and delete isEmpty variable and just write in javascript closure, in the video explained a few seconds later, but after a day of struggling, I realized it too :D

if(!cart.line_items)
    return  '...loading';


return (
    <div className={classes.toolbar}>
        <Typography className={classes.title} variant="h3"> Your Shopping Cart 
        </Typography>
        {!cart.line_items.length ? <EmptyCart /> : <FilledCart />}
       
    </div>
)

Try const isEmpty = Object.keys(cart).length && !cart.line_items.length; The data is not received form the server but the ponent is rendered and that is why at first the card is undefined.

Try using optional chaining:

const isEmpty = !cart.line_items?.length

This will ask for the array length only if the array exists, preventing undefined errors. That means it will return false either if cart.line_items == undefined, or if cart.line_items.length == 0.

Maybe i'm a bit late to the party, but i got stuck in the same part and this solved my issue (and also i think it looks pretty neat)

Issue There is no cart.line_items on the initial render since initial state is an empty object ({}).

const [cart, setCart] = useState({});

Solution Provide valid initial state for the initial render so there’s a truthy, defined cart.line_items object from which to have a length property, i.e. so !cart.line_items.length; can resolve to a value and not throw an error.

const [cart, setCart] = useState({ line_items: [] });

本文标签: