> ## Documentation Index
> Fetch the complete documentation index at: https://www.commercengine.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# React

> Integrate Commerce Engine Checkout into React apps with the useCheckout hook. Reactive state, no providers required.

Hosted Checkout provides a global React store through `useCheckout()`. No context provider is required.

## Installation

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
npm install @commercengine/checkout
```

Choose the correct authentication mode before initializing:

| Application architecture | Mode |
| - | - |
| Checkout is the only Commerce Engine integration | `managed` |
| App also uses `@commercengine/storefront` or direct session APIs | `provided` with two-way token sync |

## Checkout-only React app

Use managed mode when the React app does not use the Storefront SDK. Checkout creates and owns the anonymous/logged-in session.

Initialize once in a root component and clean up on unmount:

```tsx src/checkout-bootstrap.tsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { useEffect } from "react";
import {
  destroyCheckout,
  initCheckout,
} from "@commercengine/checkout/react";

export function CheckoutBootstrap() {
  useEffect(() => {
    initCheckout({
      storeId: import.meta.env.VITE_STORE_ID,
      apiKey: import.meta.env.VITE_API_KEY,
      environment:
        import.meta.env.VITE_CE_ENV === "production"
          ? "production"
          : "staging",
      onComplete: ({ orderNumber }) => {
        window.location.assign(`/thank-you?order=${orderNumber}`);
      },
    });

    return () => destroyCheckout();
  }, []);

  return null;
}
```

Mount `<CheckoutBootstrap />` once near the application root.

## React app with Storefront SDK

When `@commercengine/storefront` is present, managed mode would create a second independent session. Use `authMode: "provided"` and synchronize tokens in both directions.

Follow [React SDK integration](/docs/sdk/react-integration#hosted-checkout-recommended-cart-and-checkout) for the complete provided-mode pattern: storefront config with `onTokensUpdated`, session bootstrap, and checkout init and teardown.

<Warning>
  Do not use the checkout-only managed-mode setup above in a React app that also imports `@commercengine/storefront`. The two sessions diverge and the cart silently splits in two.
</Warning>

For Next.js and TanStack Start, use their dedicated SDK integration pages because the Storefront SDK callback is configured on the framework wrapper rather than inside a SPA `session` object.

## Use the hook

```tsx src/components/cart-button.tsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { useCheckout } from "@commercengine/checkout/react";

export function CartButton() {
  const { cartCount, isReady, openCart } = useCheckout();

  return (
    <button type="button" onClick={openCart} disabled={!isReady}>
      Cart ({cartCount})
    </button>
  );
}
```

```tsx src/components/add-to-cart-button.tsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { useCheckout } from "@commercengine/checkout/react";

export function AddToCartButton({
  productId,
  variantId,
  hasVariants,
}: {
  productId: string;
  variantId: string | null;
  hasVariants: boolean;
}) {
  const { addToCart, isReady } = useCheckout();
  const disabled = !isReady || (hasVariants && !variantId);

  return (
    <button
      type="button"
      disabled={disabled}
      onClick={() => addToCart(productId, variantId, 1)}
    >
      Add to cart
    </button>
  );
}
```

Pass `null` for products without variants. For products with variants, do not enable the button until the UI resolves a purchasable `variantId`.

## Open checkout directly

```tsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
function BuyNowButton() {
  const { isReady, openCheckout } = useCheckout();
  return (
    <button type="button" disabled={!isReady} onClick={openCheckout}>
      Buy now
    </button>
  );
}
```

For a product-specific Quick Buy session, configure `quickBuy` at initialization. See [Configuration](/docs/hosted-checkout/configuration).

## Hook API

| Property | Type | Description |
| - | - | - |
| `isReady` | `boolean` | iframe initialized and ready for commands |
| `isOpen` | `boolean` | overlay visibility |
| `cartCount` | `number` | current item count |
| `cartTotal` | `number` | current cart total reported by checkout |
| `cartCurrency` | `string` | currency code |
| `isLoggedIn` | `boolean` | current checkout session state |
| `user` | `UserInfo \| null` | current user decoded from the session |
| `openCart()` | function | open cart drawer |
| `openCheckout()` | function | open checkout directly |
| `close()` | function | close overlay |
| `addToCart(productId, variantId, quantity?)` | function | add an item |
| `updateTokens(accessToken, refreshToken?)` | function | update provided-mode tokens |

## Error and lifecycle handling

Use initialization callbacks for app-level behaviour:

```tsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
initCheckout({
  // ...credentials and auth mode
  onReady: () => setCheckoutAvailable(true),
  onError: ({ message }) => reportCheckoutError(message),
  onSessionError: () => showSessionRecoveryMessage(),
  onComplete: ({ orderNumber }) => navigate(`/thank-you?order=${orderNumber}`),
});
```

Do not enable cart actions until `isReady` is true. Do not initialize checkout in every route component.

## Next.js

Use a root Client Component that first calls `storefront.bootstrap()`, then initializes checkout in provided mode. Follow [Next.js SDK integration](/docs/sdk/nextjs-integration#hosted-checkout--nextjs); do not use the checkout-only managed-mode example in a Next.js storefront that imports `@commercengine/storefront`.

## Production checklist

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
[ ] correct managed/provided mode selected
[ ] one root initialization
[ ] cleanup runs on unmount
[ ] async init guarded against post-cleanup resurrection
[ ] cart buttons disabled until ready
[ ] variant ID is correct or null for simple products
[ ] onComplete and onError handled
[ ] two-way token sync when Storefront SDK is present
```

<Card title="React starter implementations" icon="github" href="https://github.com/tark-ai/ce-starter-projects">
  Review both Vite React and React meta-framework starters for complete lifecycle, catalog, and deployment patterns.
</Card>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.