> ## 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.

### NPM Package

<Card title="@commercengine/checkout" icon="npm" href="https://www.npmjs.com/package/@commercengine/checkout">
  React integration for Commerce Engine Checkout.
</Card>

### Installation

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

### Setup

Call `initCheckout` once at your app's entry point. This creates a hidden iframe in the background — it does not block rendering. The SDK resolves the hosted URL from `storeId` + `environment` using store-specific subdomains.

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

initCheckout({
  storeId: "store_xxx",
  apiKey: "ak_xxx",
  environment: "production",
});
```

<Info>
  `initCheckout` should be called once at the top level of your app, outside of any component. It is safe to call in SSR environments — it no-ops on the server.
</Info>

<Info>
  Feature flags, login methods, drawer direction, and payment provider are managed in Checkout Studio (Config API), not as SDK init options. Use `theme` only for per-session overrides.
</Info>

### Use the hook

`useCheckout()` returns reactive state and action methods. No context provider is needed.

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

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

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

### Full example

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

initCheckout({
  storeId: "store_xxx",
  apiKey: "ak_xxx",
  environment: "production",
  onComplete: (order) => {
    console.log("Order placed:", order.orderNumber);
  },
});

function Navbar() {
  const { openCart, cartCount, isReady, isLoggedIn, user } = useCheckout();

  return (
    <nav>
      {isLoggedIn && <span>Hi, {user?.firstName}</span>}
      <button onClick={openCart} disabled={!isReady}>
        Cart ({cartCount})
      </button>
    </nav>
  );
}

function ProductPage({ productId, variantId }) {
  const { addToCart } = useCheckout();

  return (
    <button onClick={() => addToCart(productId, variantId)}>
      Add to Cart
    </button>
  );
}

export default function App() {
  return (
    <>
      <Navbar />
      <ProductPage productId="product_abc" variantId="variant_xyz" />
    </>
  );
}
```

### Next.js

For Next.js, call `initCheckout` in a client component:

```tsx providers.tsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
"use client";

import { initCheckout } from "@commercengine/checkout/react";

initCheckout({
  storeId: "store_xxx",
  apiKey: "ak_xxx",
  environment: "production",
});

export function CheckoutProvider({ children }: { children: React.ReactNode }) {
  return <>{children}</>;
}
```

```tsx layout.tsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { CheckoutProvider } from "./providers";

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <CheckoutProvider>{children}</CheckoutProvider>
      </body>
    </html>
  );
}
```

Then use `useCheckout()` in any client component as usual.

### Syncing external auth

If your app manages its own authentication, pass tokens to keep checkout in sync:

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

function AuthSync({ accessToken, refreshToken }) {
  const { updateTokens } = useCheckout();

  useEffect(() => {
    if (accessToken) {
      updateTokens(accessToken, refreshToken);
    }
  }, [accessToken, refreshToken]);

  return null;
}
```

Set `authMode: "provided"` in the init config when using external auth:

```tsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
initCheckout({
  storeId: "store_xxx",
  apiKey: "ak_xxx",
  authMode: "provided",
  accessToken: "...",
  refreshToken: "...",
});
```

### Hook API reference

`useCheckout()` returns:

| Property                                     | Type               | Description                                         |
| -------------------------------------------- | ------------------ | --------------------------------------------------- |
| `isReady`                                    | `boolean`          | `true` when the checkout iframe is loaded and ready |
| `isOpen`                                     | `boolean`          | `true` when the checkout overlay is visible         |
| `cartCount`                                  | `number`           | Number of items in the cart                         |
| `cartTotal`                                  | `number`           | Cart subtotal                                       |
| `cartCurrency`                               | `string`           | Currency code (e.g. `"INR"`)                        |
| `isLoggedIn`                                 | `boolean`          | Whether a user is logged in                         |
| `user`                                       | `UserInfo \| null` | Current user info (decoded from JWT)                |
| `openCart()`                                 | `function`         | Open the cart drawer                                |
| `openCheckout()`                             | `function`         | Open checkout directly (skips cart)                 |
| `close()`                                    | `function`         | Close the overlay                                   |
| `addToCart(productId, variantId, quantity?)` | `function`         | Add an item to the cart                             |
| `updateTokens(accessToken, refreshToken?)`   | `function`         | Sync auth tokens from your app                      |
