admin管理员组

文章数量:1405636

I am facing the issue in my react application.

TypeError: Cannot read properties of undefined (reading 'requestContent')

I am using mercejs in my application. The code points to isEmpty=!cart.line_items.length;. When checked it shows the proper value. Furthermore, I have noticed that the Api returns NULL array twice and populated array the third time. Why is it so? Anyone there to help me sort this issue?

Cart.jsx

import React from "react";
import { Container, Typography, Button, Grid } from "@material-ui/core";

import useStyles from "./CartStyles";

const Cart = ({ cart }) => {
  const classes = useStyles();
  console.log("CART ",cart.line_items); 
  const isEmpty = !cart.line_items.length;

  const EmptyCart = () => {
    <Typography variant="subtitle1">
      You donot have any item in your shopping cart. Start adding some of the
      items in your shopping cart.
    </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>
        ))}
        <div className={classes.cartDetails}>
          <Typography variant="h4">
            Subtotal: {cart.subtotal.formatted_With_symbol}
            <div>
              <Button
                className={classes.emptyButton}
                size="large"
                type="button"
                variant="contained"
                color="secondary"
              >
                Empty Cart
              </Button>
              <Button
                className={classes.checkoutButton}
                size="large"
                type="button"
                variant="contained"
                color="primary"
              >
                Checkout
              </Button>
            </div>
          </Typography>
        </div>
      </Grid>
    </>;
  };

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

export default Cart;

App.js

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

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

    const fetchProducts = async() => {
        // call the product api from merce js
        const { data } = await merce.products.list();
        // populates the products
        setProducts(data);
    }

    //get element of cart
    const fetchCart = async() => {
        const cartItems = await merce.cart.retrieve();
        setCart(cartItems);
    }


    const handleAddToCart = async(productId, quantity) => {
        const itemsInCart = await merce.cart.add(productId, quantity);
        setCart(itemsInCart.cart);
    }

    useEffect(() => {
        //Calling of methods which we want to call on load of ponent
        fetchProducts();
        fetchCart();
    }, []);
    //  empty array is given so that it makes a call as soon as ponent is loaded.
    console.log(cart);
    return ( <
        div >
        <
        Navbar totalItems = { cart.total_items }
        / >   <
        Cart cart = { cart }
        /> < /
        div >
    );
};

export default App;

Error Screenshot

I am facing the issue in my react application.

TypeError: Cannot read properties of undefined (reading 'requestContent')

I am using mercejs in my application. The code points to isEmpty=!cart.line_items.length;. When checked it shows the proper value. Furthermore, I have noticed that the Api returns NULL array twice and populated array the third time. Why is it so? Anyone there to help me sort this issue?

Cart.jsx

import React from "react";
import { Container, Typography, Button, Grid } from "@material-ui/core";

import useStyles from "./CartStyles";

const Cart = ({ cart }) => {
  const classes = useStyles();
  console.log("CART ",cart.line_items); 
  const isEmpty = !cart.line_items.length;

  const EmptyCart = () => {
    <Typography variant="subtitle1">
      You donot have any item in your shopping cart. Start adding some of the
      items in your shopping cart.
    </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>
        ))}
        <div className={classes.cartDetails}>
          <Typography variant="h4">
            Subtotal: {cart.subtotal.formatted_With_symbol}
            <div>
              <Button
                className={classes.emptyButton}
                size="large"
                type="button"
                variant="contained"
                color="secondary"
              >
                Empty Cart
              </Button>
              <Button
                className={classes.checkoutButton}
                size="large"
                type="button"
                variant="contained"
                color="primary"
              >
                Checkout
              </Button>
            </div>
          </Typography>
        </div>
      </Grid>
    </>;
  };

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

export default Cart;

App.js

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

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

    const fetchProducts = async() => {
        // call the product api from merce js
        const { data } = await merce.products.list();
        // populates the products
        setProducts(data);
    }

    //get element of cart
    const fetchCart = async() => {
        const cartItems = await merce.cart.retrieve();
        setCart(cartItems);
    }


    const handleAddToCart = async(productId, quantity) => {
        const itemsInCart = await merce.cart.add(productId, quantity);
        setCart(itemsInCart.cart);
    }

    useEffect(() => {
        //Calling of methods which we want to call on load of ponent
        fetchProducts();
        fetchCart();
    }, []);
    //  empty array is given so that it makes a call as soon as ponent is loaded.
    console.log(cart);
    return ( <
        div >
        <
        Navbar totalItems = { cart.total_items }
        / >   <
        Cart cart = { cart }
        /> < /
        div >
    );
};

export default App;

Error Screenshot

Share Improve this question asked Sep 23, 2021 at 5:31 Asad MehmoodAsad Mehmood 3423 gold badges11 silver badges22 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 3

Issue

The issue is caused by your initial cart state in App:

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

It's an empty object ({}) and passed on to the Cart ponent that then assumes it has a line_items property.

const isEmpty = !cart.line_items.length;

Since cart.line_items is undefined an error is thrown when you then attempt to reference the length property.

Solution

Use an Optional Chaining operator to guard the null access.

const isEmpty = !cart.line_items?.length;

Or guard clause/null check

const isEmpty = !(cart.line_items && cart.line_items.length);

Additional

Furthermore, I have noticed that the Api returns NULL array twice and populated array the third time. Why is it so? Anyone there to help me sort this issue?

This is likely a bination of the console.log("CART ",cart.line_items); in the function ponent body as an unintentional side-effect and the app being rendered into a React.StrictMode ponent that intentionally double invokes certain functions and ponent methods twice as a way to help you detect unintentional side-effects.

Detecting unexpected side effects

Strict mode can’t automatically detect side effects for you, but it can help you spot them by making them a little more deterministic. This is done by intentionally double-invoking the following functions:

  • Class ponent constructor, render, and shouldComponentUpdate methods
  • Class ponent static getDerivedStateFromProps method
  • Function ponent bodies
  • State updater functions (the first argument to setState)
  • Functions passed to useState, useMemo, or useReducer

本文标签: javascriptTypeError Cannot read properties of undefined (reading 39requestContent39)Stack Overflow