Part 85: Implementing the Add-to-Cart Functionality with API Integration

[Pages] Shopping Cart (Exercises)

[Pages] Shopping Cart (Exercises)

In the world of e-commerce, a seamless shopping experience is crucial. One essential feature is allowing users to add items to their shopping cart and navigate there effortlessly. In our previous post, we set up an "Add to Cart" button on each product page that logged the product details to the console. Now, we will take the final step by integrating this functionality with our backend API to actually add items to the cart and redirect users to the cart page.

Step 1: Encapsulating Cart Logic in a Component

To keep our code clean and maintainable, we'll handle the API interaction directly within the AddToCartWidget component. This encapsulates the cart-related functionality and makes it easier to manage.

Setting Up the API Request

We'll use useMutation from React Query to handle the API request. This allows us to manage the request state effectively, including loading and error states.

// File: components/AddToCartWidget.js

const { useState } = require('react');
import { useRouter } from 'next/router';
import { useMutation } from 'react-query';
import { fetchJson } from '../lib/api';
import Button from './Button';

function AddToCartWidget({ productId }) {
  const router = useRouter();
  const [quantity, setQuantity] = useState(1);

  const mutation = useMutation(() =>
    fetchJson('/api/cart', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ productId, quantity })
    })
  );

  const handleClick = async () => {
    console.log('should add to cart:', { productId, quantity });
    await mutation.mutateAsync();
    router.push('/cart');
  };

  return (
    <div className="py-2">
      <input type="number" min="1"
        className="border rounded px-3 py-1 mr-2 w-16 text-right"
        value={quantity.toString()}
        onChange={(event) => setQuantity(parseInt(event.target.value))}
      />
      {mutation.isLoading ? (
        <p>Loading...</p>
      ) : (
        <Button onClick={handleClick}>
          Add to cart
        </Button>
      )}
    </div>
  );
}

export default AddToCartWidget;

Explanation

  • Router Integration: We use useRouter from Next.js to handle navigation. After a successful API request, we navigate the user to the /cart page.

  • Mutation Setup: With useMutation, we define the POST request to the /api/cart endpoint. We send the productId and quantity in the request body.

  • Loading State Management: The mutation.isLoading flag helps us manage the UI during the request. While the request is in progress, we display a "Loading..." message instead of the button to prevent duplicate submissions.

Step 2: Testing the Integration

With the functionality in place, let's test it:

  1. Navigate to a product page.

  2. Select a quantity and click "Add to Cart."

  3. Verify that you are redirected to the cart page, and the selected product with the specified quantity is displayed.

Conclusion

By following these steps, we've successfully integrated the add-to-cart functionality with our backend API, enhancing the user experience by automatically redirecting users to their cart. This improvement not only makes the shopping process smoother but also demonstrates a robust way to manage state and side effects in a React application using React Query.

This was the final step in our series on building an interactive product page. Congratulations on implementing this feature! As a next step, you might consider refactoring the mutation logic into a custom React hook to further improve code organization and reusability. Happy coding!

Last updated