Products & Payments Hooks
Hooks for accessing the product catalog, selection state, and payment information.
useProducts()
Access the product catalog and selection state. Only re-renders when the selected product changes.
const { products, selected, select } = useProducts()
return (
<div>
{products.map((p) => (
<button key={p.id} onClick={() => select(p.id)}>
{p.name} - {p.price}/{p.period}
</button>
))}
{selected && <p>Selected: {selected.displayName}</p>}
</div>
)| Property | Type | Description |
|---|---|---|
products | RuntimeProduct[] | All configured products with resolved pricing |
selected | RuntimeProduct | null | Currently selected product |
select | (productId: string) => void | Select a product by ID |
RuntimeProduct (key fields)
| Field | Type | Description |
|---|---|---|
id | string | Product identifier |
name | string | Product name from config |
displayName | string | Resolved display name |
price | string | Formatted price (e.g. "$9.99") |
rawPrice | number | Price in cents/smallest unit |
monthlyPrice | string | Normalized monthly price |
weeklyPrice | string | Normalized weekly price |
dailyPrice | string | Normalized daily price |
yearlyPrice | string | Normalized yearly price |
period | string | Billing period label (e.g. "month") |
periodly | string | Adverb form (e.g. "monthly") |
periodDays | number | Period length in days |
currencyCode | string | ISO currency code (e.g. "USD") |
currencySymbol | string | Currency symbol (e.g. "$") |
hasTrial | boolean | Whether the product has a trial |
trialDays | number | Trial length in days |
trialPrice | string | Formatted trial price |
paidTrial | boolean | Whether the trial has a cost |
storePriceId | string | Price ID from the payment provider |
stripePriceId | string | Stripe price ID |
paddlePriceId | string | Paddle price ID |
usePayment()
Payment hook for triggering purchases and reading loading/error state. Only re-renders when payment state changes.
const { loading, error, purchase } = usePayment()| Property | Type | Description |
|---|---|---|
loading | boolean | Payment operation in progress |
error | string | null | Last payment error message |
purchase | (productId: string, options?) => Promise<boolean> | Purchase a product using the card on file |
purchase(productId, options?)
Charges the card already on file for the given product. This is typically used on upsell pages after the user has already entered their card on the paywall via StripePaymentForm.
Automatically handles 3DS authentication, trial periods, and tracks purchase.complete / subscription.created events. Sets loading and error state during the operation.
In dev mode, the purchase simulates a successful charge after a short delay.
const { products } = useProducts()
const { goToNextPage } = useNavigation()
const { loading, purchase } = usePayment()
const upsellProduct = products.find((p) => p.id.startsWith('upsell'))
const handleAdd = () => {
if (!upsellProduct) return
purchase(upsellProduct.id, {
onSuccess: () => goToNextPage(),
onError: (error) => console.error(error),
})
}Options
| Field | Type | Description |
|---|---|---|
onSuccess | () => void | Called when the purchase completes successfully |
onError | (error: string) => void | Called with the error message on failure |
Returns a Promise<boolean> — true on success, false on failure.