Part 82: Displaying Cart Items with React: A Step-by-Step Guide

[Pages] Shopping Cart (Exercises)

[Pages] Shopping Cart (Exercises)

Creating an intuitive and informative cart page is a crucial aspect of any e-commerce application. In this blog post, we'll walk through the process of fetching and displaying cart items using React, focusing on rendering these items in an HTML table with Tailwind CSS for styling. We'll also explore how to calculate and display item totals and a grand total for the cart.

Step 1: Display Cart Items in a Table

The first step is to display the cart items we fetched earlier in a structured table format. We'll create a CartTable component to handle the display logic, ensuring each cart item is represented with its product title, price, and quantity.

Initial Implementation

Here's how we can start by simply listing each item in a table:

// File: pages/cart.js

import { useQuery } from 'react-query';
import Page from '../components/Page';
import { fetchJson } from '../lib/api';

function CartTable({ cartItems }) {
  return (
    <table>
      <thead>
        <tr>
          <th className="px-4 py-2">Product</th>
          <th className="px-4 py-2">Price</th>
          <th className="px-4 py-2">Quantity</th>
        </tr>
      </thead>
      <tbody>
        {cartItems.map((cartItem) => (
          <tr key={cartItem.id}>
            <td className="px-4 py-2">{cartItem.product.title}</td>
            <td className="px-4 py-2 text-right">{cartItem.product.price}</td>
            <td className="px-4 py-2 text-right">{cartItem.quantity}</td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}

function CartPage() {
  const query = useQuery('cartItems', () => fetchJson('/api/cart'));
  const cartItems = query.data;

  console.log('[CartPage] cartItems:', cartItems);
  return (
    <Page title="Cart">
      {cartItems && <CartTable cartItems={cartItems} />}
    </Page>
  );
}

export default CartPage;

Explanation

  • Table Structure: We use a simple HTML table with headings for "Product", "Price", and "Quantity".

  • Mapping Items: We iterate over the cartItems array to create a table row for each item.

  • Tailwind CSS: Utility classes like px-4 and py-2 are used for padding, while text-right aligns numeric content to the right.

Step 2: Calculating Totals and Formatting Prices

Next, we'll enhance our table to include a total for each item and a grand total for the cart. We'll also format prices to display as currency.

Enhancements

  1. Helper Functions: We introduce buildCart to calculate item totals and a grand total, and formatCurrency to format numbers as dollar amounts.

  2. Table Modifications: We add a column for item totals and a footer for the grand total.

// File: pages/cart.js

import { useQuery } from 'react-query';
import Page from '../components/Page';
import { fetchJson } from '../lib/api';

function formatCurrency(value) {
  return '$' + value.toFixed(2);
}

function buildCart(cartItems) {
  let total = 0.0;
  const items = [];
  for (const cartItem of cartItems) {
    const itemTotal = cartItem.product.price * cartItem.quantity;
    total += itemTotal;
    items.push({ ...cartItem, total: itemTotal });
  }
  return { items, total };
}

function CartTable({ cartItems }) {
  const cart = buildCart(cartItems);
  return (
    <table>
      <thead>
        <tr>
          <th className="px-4 py-2">Product</th>
          <th className="px-4 py-2">Price</th>
          <th className="px-4 py-2">Quantity</th>
          <th className="px-4 py-2">Total</th>
        </tr>
      </thead>
      <tbody>
        {cart.items.map((cartItem) => (
          <tr key={cartItem.id}>
            <td className="px-4 py-2">{cartItem.product.title}</td>
            <td className="px-4 py-2 text-right">{formatCurrency(cartItem.product.price)}</td>
            <td className="px-4 py-2 text-right">{cartItem.quantity}</td>
            <td className="px-4 py-2 text-right">{formatCurrency(cartItem.total)}</td>
          </tr>
        ))}
      </tbody>
      <tfoot>
        <tr>
          <th className="px-4 py-2 text-left">Total</th>
          <th></th>
          <th></th>
          <th className="px-4 py-2 text-right">{formatCurrency(cart.total)}</th>
        </tr>
      </tfoot>
    </table>
  );
}

Explanation

  • Total Calculation: The buildCart function calculates a total for each item and a grand total for the cart.

  • Currency Formatting: The formatCurrency function ensures prices are displayed in a consistent currency format.

  • Table Footer: A footer row is added to display the grand total, enhancing the table's functionality.

Conclusion

By following these steps, we have successfully transformed our cart page into a comprehensive display of cart items, including individual and grand totals. This setup not only improves user experience but also provides clarity and precision in the shopping process. As you continue developing your application, consider further enhancements such as handling cart updates and integrating additional styling for a polished look.

Last updated