Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactJS -- TypeError: Cannot read property 'name' of undefined

Tags:

reactjs

I have App.js with products and cart.

import React, { Component } from 'react';
import { connect } from 'react-redux';
import ProductGrid from './components/ProductGrid';
import CartTable from './components/CartTable';
import { fetchProducts } from './state/product/actions';
import { fetchCart } from './state/cart/actions';

class App extends Component {
  componentDidMount() {
    this.props.fetchProducts();
    this.props.fetchCart();
  }

  render() {
    const {
      isProductLoading,
      products,
      cart,
    } = this.props;

    if(isProductLoading) {
      return <h2>loading...</h2>
    }

    return (
      <div>
        <h1>Shop application!</h1>
        <ProductGrid
          products={products}
        />
        <h1>Cart</h1>
        <CartTable
          cart={cart}
        />
      </div>
    );
  }
}

const getProductById = (products, productId) => products.find(p => p._id === productId);

const populateCartItems = (c, p) => ({
  ...c,
  items: c.items.map(i => ({
    ...i,
    product: getProductById(p, i.productId),
  })),
});

const mapStateToProps = (state) => ({
  isProductLoading: state.product.isLoading,
  products: state.product.products,
  cart: populateCartItems(state.cart.cart, state.product.products),
});

const mapDispatchToProps = {
  fetchProducts,
  fetchCart,
};


export default connect(mapStateToProps, mapDispatchToProps)(App);

Problem is with the populate of cart and products objects.

import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';

const Wrapper = styled.table`
  width: 100%;
  border-collapse: collapse;

  td, th {
    border: 1px solid #DDD;
    padding: 8px;
    text-align: left;
  }

  tr:nth-child(even) {
    background: #DDD;
  }
`;

const CartTable = ({ cart }) => (

  <Wrapper>
    <thead>
      <tr>
        <th>Item Name</th>
        <th>Item Price</th>
        <th>Item Quantity</th>
      </tr>
    </thead>
    <tbody>
      {cart.items.map(item => (
        <tr key={item.productId}>
          <td>{item.product.name}</td>
          <td>{}</td>
          <td>{item.quantity}</td>
        </tr>
      ))}
    </tbody>
  </Wrapper>
);

CartTable.propTypes = {
  cart: PropTypes.shape({
    items: PropTypes.arrayOf(PropTypes.shape({
      product: PropTypes.shape({
        name: PropTypes.string.isRequired,
        price: PropTypes.number.isRequired,
      }).isRequired,
      productId: PropTypes.string.isRequired,
      quantity: PropTypes.number.isRequired,
    })).isRequired,
  }).isRequired,
};

export default CartTable;

When passing cart object to CartTable, I get error:

TypeError: Cannot read property 'name' of undefined

  30 | <tbody>
  31 |   {cart.items.map(item => (
  32 |     <tr key={item.productId}>
> 33 |       <td>{item.product.name}</td>
  34 |       <td>{}</td>
  35 |       <td>{item.quantity}</td>
  36 |     </tr>

I'm quite sure the cart object is working fine in App.js (tested with console.log) but after it has passed to CartTable, populated product object is not found.

like image 445
user3407101 Avatar asked Jul 01 '26 09:07

user3407101


1 Answers

You're not validating your data before trying to render it. A simple fix for the problem would be to change your map function into:

{cart.items && !isProductLoading ? cart.items.map(item => (
  <tr key={item.productId ? item.productId : null}>
    <td>{item.product.name ? item.product.name : ''}</td>
    <td>{}</td>
    <td>{item.quantity ? item.quantity : null}</td>
  </tr>
)) : null}
like image 197
MstrQKN Avatar answered Jul 02 '26 22:07

MstrQKN