---
title: "Ecommerce — Frontend React Utilities"
aliases: [ecommerce-react-hooks, payload-ecommerce-frontend, useCart, usePayments]
tags: [payloadcms, ecommerce, react, hooks, stripe, cart]
sources: [raw/ecommerce__frontend.md]
created: 2026-05-15
updated: 2026-05-15
---

## Overview

`@payloadcms/plugin-ecommerce/client/react` exports a context provider + 6 focused hooks for managing cart, addresses, payments, and currency on the frontend. All hooks require `EcommerceProvider` to be mounted above them in the component tree.

## EcommerceProvider

Wrap your app (or checkout subtree) with this provider:

```tsx
import { EcommerceProvider } from '@payloadcms/plugin-ecommerce/client/react'
import { stripeAdapterClient } from '@payloadcms/plugin-ecommerce/payments/stripe'
import { USD, EUR } from '@payloadcms/plugin-ecommerce'

export const Providers = ({ children }) => (
  <EcommerceProvider
    enableVariants={true}
    currenciesConfig={{
      supportedCurrencies: [USD, EUR],
      defaultCurrency: 'USD',
    }}
    paymentMethods={[stripeAdapterClient]}
  >
    {children}
  </EcommerceProvider>
)
```

### Key Props

| Prop | Default | Notes |
|------|---------|-------|
| `addressesSlug` | `addresses` | Collection slug |
| `cartsSlug` | `carts` | Collection slug |
| `customersSlug` | `users` | Collection slug |
| `currenciesConfig` | — | `{ supportedCurrencies, defaultCurrency }` |
| `paymentMethods` | — | Array of client-side payment adapters |
| `enableVariants` | `true` | Product variants support |
| `syncLocalStorage` | `true` | Persist cart ID across reloads; `{ key: 'cart' }` for custom key |
| `api.apiRoute` | `/api` | Payload API base route |
| `api.cartsFetchQuery` | — | Extra depth/select/populate for cart fetches |
| `debug` | `false` | Verbose console output |

## Hooks Reference

### useCart

Manages cart state and item operations.

```tsx
const { cart, addItem, removeItem, incrementItem, decrementItem, clearCart, isLoading } = useCart()
```

| Property | Type | Notes |
|----------|------|-------|
| `cart` | `Cart \| null` | Current cart state |
| `addItem` | `(item, quantity?) => void` | Add product/variant |
| `removeItem` | `(id) => void` | Remove by ID |
| `incrementItem` | `(id) => void` | +1 quantity |
| `decrementItem` | `(id) => void` | -1 quantity; removes at 0 |
| `clearCart` | `() => void` | Empty the cart |
| `isLoading` | `boolean` | Any async op in flight |

### usePayments

Two-step checkout: `initiatePayment` → `confirmOrder`.

```tsx
const { initiatePayment, confirmOrder, paymentMethods, selectedPaymentMethod, isLoading } = usePayments()
```

**Step 1 — initiate** (cart verified, transaction created, no order yet):
```ts
const data = await initiatePayment('stripe', {
  additionalData: { customerEmail, billingAddress, shippingAddress },
})
// data.client_secret → complete payment with Stripe.js
```

**Step 2 — confirm** (after Stripe.js confirms payment on client):
```ts
const data = await confirmOrder('stripe', {
  additionalData: { paymentIntentID: paymentIntent.id, customerEmail },
})
// data.orderID → redirect to order page
```

> Order is only created after `confirmOrder`. For off-site redirects (e.g. Stripe callback URL), route the relevant info back before calling `confirmOrder`.

### useAddresses

```tsx
const { addresses, createAddress, updateAddress, isLoading } = useAddresses()
```

| Property | Type |
|----------|------|
| `addresses` | `Address[]` |
| `createAddress` | `(data) => Promise<Address>` |
| `updateAddress` | `(id, partial) => Promise<Address>` |

### useCurrency

Formats prices (stored as integers) for display:

```tsx
const { currency, setCurrency, formatPrice, currenciesConfig } = useCurrency()

<div>{formatPrice(amount)}</div>  // handles decimals per currency
```

- All prices are stored as integers (avoids float precision issues)
- `formatPrice` accounts for currency-specific decimal places

### useEcommerceConfig

Access collection slugs and API settings for custom API calls:

```tsx
const { cartsSlug, customersSlug, addressesSlug, api } = useEcommerceConfig()
const endpoint = `${api.apiRoute}/${cartsSlug}`
```

### useEcommerce (unified hook)

Combines all hooks. Also exposes session management methods:

```tsx
const {
  cart, addresses, config, isLoading,
  selectedPaymentMethod, clearSession,
  onLogin, onLogout, mergeCart, refreshCart,
} = useEcommerce()
```

## Session Management

### onLogin

Call after successful login to merge guest cart → user cart:

```tsx
const response = await fetch('/api/users/login', { method: 'POST', body: ... })
if (response.ok) await onLogin()
```

Handles: fetch user data → merge guest items → transfer guest cart (if user has none) → clear guest secrets.

### onLogout / clearSession

```tsx
await fetch('/api/users/logout', { method: 'POST' })
onLogout() // alias for clearSession()
```

Clears: cart data, cart ID, cart secret, addresses, user state (memory + localStorage).

### mergeCart

Manual cart merge (e.g. custom flows):

```ts
const mergedCart = await mergeCart('user-cart-id', 'guest-cart-id', 'guest-cart-secret')
// Source cart is deleted after merge; matching items have quantities combined
```

### refreshCart

Force-sync cart from server:

```tsx
const { refreshCart } = useEcommerce()
<button onClick={refreshCart}>Refresh</button>
```

## Key Takeaways

- **Two-step checkout**: `initiatePayment` verifies cart and creates a transaction; `confirmOrder` creates the actual order — never skip step 2.
- **Integer prices**: All prices stored as integers; always use `formatPrice()` for display — never divide manually.
- **Guest → auth cart merge**: Call `onLogin()` after login, not after — it handles the merge automatically.
- **`syncLocalStorage`**: Cart ID persists across reloads by default; use `{ key: 'custom' }` to avoid key collisions.
- **`useEcommerce` is the kitchen-sink hook**: Use focused hooks (`useCart`, `usePayments`) for tree-shaking; `useEcommerce` for convenience when you need everything.
- **`api.cartsFetchQuery.depth`**: Bump to 2+ if you need populated product/variant data in the cart response.

## Related

- [[wiki/payloadcms/ecommerce|Ecommerce Plugin — Setup & Overview]]
- [[wiki/payloadcms/ecommerce-advanced|Ecommerce — Advanced / Piecemeal Collections API]]
- [[wiki/payloadcms/authentication-overview|Authentication — Overview]]
- [[wiki/payloadcms/queries|Queries — depth, select, populate]]

## Sources

- `raw/ecommerce__frontend.md` — https://payloadcms.com/docs/ecommerce/frontend
