6.4 KiB
| title | aliases | tags | sources | created | updated | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Ecommerce — Frontend React Utilities |
|
|
|
2026-05-15 | 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:
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.
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.
const { initiatePayment, confirmOrder, paymentMethods, selectedPaymentMethod, isLoading } = usePayments()
Step 1 — initiate (cart verified, transaction created, no order yet):
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):
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 callingconfirmOrder.
useAddresses
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:
const { currency, setCurrency, formatPrice, currenciesConfig } = useCurrency()
<div>{formatPrice(amount)}</div> // handles decimals per currency
- All prices are stored as integers (avoids float precision issues)
formatPriceaccounts for currency-specific decimal places
useEcommerceConfig
Access collection slugs and API settings for custom API calls:
const { cartsSlug, customersSlug, addressesSlug, api } = useEcommerceConfig()
const endpoint = `${api.apiRoute}/${cartsSlug}`
useEcommerce (unified hook)
Combines all hooks. Also exposes session management methods:
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:
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
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):
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:
const { refreshCart } = useEcommerce()
<button onClick={refreshCart}>Refresh</button>
Key Takeaways
- Two-step checkout:
initiatePaymentverifies cart and creates a transaction;confirmOrdercreates 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.useEcommerceis the kitchen-sink hook: Use focused hooks (useCart,usePayments) for tree-shaking;useEcommercefor 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
- wiki/payloadcms/ecommerce-advanced
- wiki/payloadcms/authentication-overview
- wiki/payloadcms/queries
Sources
raw/ecommerce__frontend.md— https://payloadcms.com/docs/ecommerce/frontend