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.
item.productis undefined. Are you sure that all the items' product are set?