React Hooks Reference
All hooks from @cimplify/sdk/react with signatures, return types, and usage.
Data and commerce hooks require <CimplifyProvider />. Checkout hooks (useCheckout, useElements) require <ElementsProvider />.
All data hooks share a module-scoped cache (Map) that survives re-renders and is shared across components. Changing location via setCurrentLocation invalidates all caches since prices are location-dependent.
Data Hooks
useProducts(opts?)
| Option | Type |
|---|---|
category? | string |
collection? | string |
search? | string |
featured? | boolean |
limit? | number |
enabled? | boolean |
Returns { products, isLoading, error, refetch, is_complete, pagination }.
const { products, isLoading, error, refetch, is_complete } = useProducts({
category: 'mains',
limit: 10,
});useProduct(slugOrId)
Auto-detects slug vs ID format. Returns { product, isLoading, error, refetch }.
const { product, isLoading } = useProduct('jollof-rice'); // by slug
const { product: p2 } = useProduct('prod_abc123'); // by IDuseCategories(opts?)
Returns { categories, isLoading, error, refetch }.
const { categories, isLoading } = useCategories();useCollections(opts?)
Returns { collections, isLoading, error, refetch }.
const { collections, isLoading } = useCollections();useCollection(id)
Returns { collection, isLoading, error, refetch }.
const { collection, isLoading } = useCollection('col_summer2025');useBundle(id)
Returns { bundle, isLoading, error, refetch }.
const { bundle, isLoading } = useBundle('bun_family_meal');useComposite(id)
Returns { composite, isLoading, error, refetch }.
const { composite, isLoading } = useComposite('comp_build_your_bowl');useSearch(query, opts?)
Returns { results, isLoading, error, refetch }.
const { results, isLoading } = useSearch('espresso', { limit: 5 });useLocations(opts?)
Returns { locations, isLoading, error, refetch }.
const { locations, isLoading } = useLocations();Commerce Hooks
useCart(opts?)
Optimistic cart state -- UI updates instantly, syncs with server after.
| Return field | Type |
|---|---|
items | CartItem[] |
itemCount | number |
subtotal | number |
tax | number |
total | number |
currency | string |
isEmpty | boolean |
isLoading | boolean |
addItem | (product, quantity?, options?) => void |
removeItem | (itemId) => void |
updateQuantity | (itemId, quantity) => void |
clearCart | () => void |
sync | () => void |
const { items, total, addItem, removeItem, updateQuantity } = useCart();
// addItem signature
addItem(product, 2, {
variantId: 'var_large',
locationId: 'loc_01',
quoteId: 'qt_abc',
addOnOptionIds: ['addon_oat'],
bundleSelections: [{ productId: 'prod_1', quantity: 1 }],
compositeSelections: [{ groupId: 'grp_1', productId: 'prod_2' }],
specialInstructions: 'Extra hot',
});useOrder(orderId, opts?)
Returns { order, isLoading, error, refetch }. Supports polling for real-time order status updates.
const { order, isLoading } = useOrder('ord_abc123', {
poll: true,
pollInterval: 5000, // ms, default 5000
});
// order?.status updates automatically while pollinguseQuote(input, opts?)
Fetches a price quote for a product configuration. Auto-refreshes 30 seconds before expiry by default.
| Input field | Type |
|---|---|
productId | string (required) |
variantId? | string |
locationId? | string |
quantity? | number |
addOnOptionIds? | string[] |
bundleSelections? | BundleSelection[] |
compositeSelections? | CompositeSelection[] |
Returns { quote, isLoading, error, refresh, isExpired, messages }.
const { quote, isExpired, refresh, messages } = useQuote(
{
productId: 'prod_abc',
variantId: 'var_large',
addOnOptionIds: ['addon_oat', 'addon_syrup'],
quantity: 2,
},
{ autoRefresh: true, refreshBeforeExpiryMs: 30000 },
);
// quote?.total, quote?.breakdown, quote?.expiresAt
// messages contains pricing notes (e.g., "Bulk discount applied")Checkout Hooks
useElements()
Returns the CimplifyElements instance from ElementsProvider, or null before initialization.
const elements = useElements();
// Access underlying element instances
const payment = elements?.getElement('payment');
const isAuthed = elements?.isAuthenticated();useCheckout()
Returns { submit, process, isLoading }. Requires ElementsProvider.
const { process, isLoading } = useCheckout();
const result = await process({
cart_id: cartId,
order_type: 'delivery',
location_id: locationId,
enroll_in_link: true,
timeout_ms: 180_000,
on_status_change: (status, context) => {
console.log(status, context.display_text);
},
});
if (result.success) {
router.push('/order/' + result.order?.id);
}Important Patterns
| Pattern | Detail |
|---|---|
| Shared cache | Module-scoped Map, survives re-renders, shared across all components. |
| Location invalidation | Changing location clears all caches because prices are location-dependent. |
| Slug detection | useProduct auto-detects slug (no underscore prefix) vs ID (prod_). |
| Order polling | useOrder with { poll: true } refetches at pollInterval until terminal status. |
| Quote auto-refresh | useQuote refreshes 30s before expiry by default to keep prices valid. |
| Optimistic cart | useCart updates UI instantly, then syncs mutations to the server. |