CartItems
Description
A render props component that provides cart items data and operations. Handles loading states and integrates with the cart context to provide item management functionality.
Import
import { CartItems } from '@components/frontStore/cart/CartItems';
Usage
import { CartItems } from '@components/frontStore/cart/CartItems';
function Cart() {
return (
<CartItems>
{({ items, loading, isEmpty, totalItems, onRemoveItem }) => (
<div>
{isEmpty ? (
<p>Your cart is empty</p>
) : (
<ul>
{items.map(item => (
<li key={item.cartItemId}>
{item.productName} - {item.qty}
<button onClick={() => onRemoveItem(item.cartItemId)}>
Remove
</button>
</li>
))}
</ul>
)}
</div>
)}
</CartItems>
);
}
Props
| Name | Type | Required | Description |
|---|---|---|---|
| children | RenderFunction | Yes | Render function receiving cart data |
Render Function Props
The render function receives an object with:
| Name | Type | Description |
|---|---|---|
| items | CartItem[] | Array of cart items |
| showPriceIncludingTax | boolean | Whether to show prices with tax |
| loading | boolean | True when cart is loading |
| isEmpty | boolean | True when cart has no items |
| totalItems | number | Total quantity of items |
| onRemoveItem | (itemId: string) => Promise<void> | Function to remove an item |
Examples
Basic Cart List
import { CartItems } from '@components/frontStore/cart/CartItems';
function ShoppingCart() {
return (
<CartItems>
{({ items, isEmpty, onRemoveItem }) => {
if (isEmpty) {
return <p>Your cart is empty</p>;
}
return (
<div>
{items.map(item => (
<div key={item.cartItemId}>
<h3>{item.productName}</h3>
<p>Price: {item.productPrice.text}</p>
<p>Quantity: {item.qty}</p>
<button onClick={() => onRemoveItem(item.cartItemId)}>
Remove
</button>
</div>
))}
</div>
);
}}
</CartItems>
);
}
With Loading State
import { CartItems } from '@components/frontStore/cart/CartItems';
function Cart() {
return (
<CartItems>
{({ items, loading, isEmpty }) => {
if (loading) {
return <div>Loading cart...</div>;
}
if (isEmpty) {
return <p>Your cart is empty</p>;
}
return (
<ul>
{items.map(item => (
<li key={item.cartItemId}>
{item.productName} - Qty: {item.qty}
</li>
))}
</ul>
);
}}
</CartItems>
);
}
With Price Display
import { CartItems } from '@components/frontStore/cart/CartItems';
function CartTable() {
return (
<CartItems>
{({ items, showPriceIncludingTax, onRemoveItem }) => (
<table>
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{items.map(item => {
const price = showPriceIncludingTax
? item.finalPriceInclTax
: item.finalPrice;
const total = showPriceIncludingTax
? item.lineTotalInclTax
: item.lineTotal;
return (
<tr key={item.cartItemId}>
<td>{item.productName}</td>
<td>{price.text}</td>
<td>{item.qty}</td>
<td>{total.text}</td>
<td>
<button onClick={() => onRemoveItem(item.cartItemId)}>
Remove
</button>
</td>
</tr>
);
})}
</tbody>
</table>
)}
</CartItems>
);
}
Complete Example
import { CartItems } from '@components/frontStore/cart/CartItems';
import { Image } from '@components/common/Image';
function CartPage() {
return (
<div className="cart-page">
<h1>Shopping Cart</h1>
<CartItems>
{({
items,
loading,
isEmpty,
totalItems,
showPriceIncludingTax,
onRemoveItem
}) => {
if (loading) {
return (
<div className="loading">
<p>Loading your cart...</p>
</div>
);
}
if (isEmpty) {
return (
<div className="empty-cart">
<p>Your cart is empty</p>
<a href="/products">Continue Shopping</a>
</div>
);
}
return (
<div className="cart-content">
<p className="item-count">{totalItems} items in cart</p>
<div className="cart-items-list">
{items.map(item => {
const price = showPriceIncludingTax
? item.finalPriceInclTax
: item.finalPrice;
return (
<div key={item.cartItemId} className="cart-item">
{item.thumbnail && (
<Image
src={item.thumbnail}
alt={item.productName}
width={100}
height={100}
/>
)}
<div className="item-details">
<h3>{item.productName}</h3>
<p>SKU: {item.productSku}</p>
{item.variantOptions && (
<div className="options">
{item.variantOptions.map(opt => (
<span key={opt.attributeCode}>
{opt.attributeName}: {opt.optionText}
</span>
))}
</div>
)}
</div>
<div className="item-pricing">
<p>Price: {price.text}</p>
<p>Quantity: {item.qty}</p>
<p className="subtotal">
Subtotal: {item.subTotal.text}
</p>
</div>
<button
className="remove-btn"
onClick={() => onRemoveItem(item.cartItemId)}
>
Remove
</button>
</div>
);
})}
</div>
</div>
);
}}
</CartItems>
</div>
);
}
CartItem Interface
Each item in the items array has:
interface CartItem {
cartItemId: string;
productId: string;
productSku: string;
productName: string;
productUrl: string;
thumbnail?: string;
qty: number;
productPrice: { value: number; text: string };
finalPrice: { value: number; text: string };
finalPriceInclTax: { value: number; text: string };
lineTotal: { value: number; text: string };
lineTotalInclTax: { value: number; text: string };
subTotal: { value: number; text: string };
variantOptions?: Array<{
attributeCode: string;
attributeName: string;
optionText: string;
}>;
// ... other fields
}
Price Fields
Different price fields available:
- productPrice: Base product price
- productPriceInclTax: Base price with tax
- finalPrice: Price after discounts (excl. tax)
- finalPriceInclTax: Price after discounts (incl. tax)
- lineTotal: Item total (qty × price, excl. tax)
- lineTotalInclTax: Item total (qty × price, incl. tax)
- subTotal: Subtotal for the item
Use showPriceIncludingTax to determine which price to display.
Features
- Render Props Pattern: Flexible UI implementation
- Loading State: Automatic loading management
- Empty State: isEmpty flag for easy empty cart handling
- Item Count: Total items count
- Remove Handler: Built-in remove functionality
- Tax Configuration: Respects tax display settings
- Type Safe: Full TypeScript support
Related Components
- CartContext - Shopping cart context
- AddToCart - Add to cart component
- Area - Component area system