# React app

React apps can use Plandalf two ways. For simple checkout buttons, load the browser SDK once and render `data-plandalf-present` in JSX. For app-wide state, gates, and hooks, use the React package.

> [!NOTE]
> **Start with attributes, graduate to hooks**
> The Numi share-code generator recommends attributes for the first install because the SDK auto-discovers elements even when React renders them after page load.

## The path

1.  Load the SDK once

    Add the organization SDK to your shell document, or let `PlandalfProvider` manage the SDK instance.

2.  Render a buying action

    Use `data-plandalf-present` for a trigger button or `data-plandalf-mount` for inline checkout.

3.  Add identity only when needed

    Call `identify()` or pass per-call `user` when checkout must know the logged-in customer.

4.  Subscribe to events for app behavior

    Use FlowHandle events when the React app needs to update UI after checkout state changes.

## Choose an integration style

- [Attribute-first](#attribute-first) — Best for marketing CTAs, pricing screens, and simple in-app upgrade buttons.

- [React package](#react-package) — Best when the app needs hooks, gates, context, and shared SDK state.

## Attribute-first

```tsx
export function UpgradeButton() {
  return (
    <button
      data-plandalf-present="pro-plan"
      data-plandalf-frame="modal"
      data-plandalf-mode="test"
    >
      Upgrade
    </button>
  );
}
```

For inline checkout, mount into a stable container.

```tsx
export function CheckoutPanel() {
  return (
    <div
      data-plandalf-mount="pro-plan"
      data-plandalf-apply-promo="early-bird"
      style={{ minHeight: 480 }}
    />
  );
}
```

## React package

These are v2 workspace examples, not instructions for the older public npm release. Read the [package version note](https://plandalf.com/docs/packages/react) before using them; the organization-hosted script and attributes above are the current recommended install path.

<scalar-tabs default="Provider">
<scalar-tab title="Provider">

```tsx
import { PlandalfProvider } from "@plandalf/react";

export function Root() {
  return (
    <PlandalfProvider apiBase="https://acme.plandalf.dev">
      <App />
    </PlandalfProvider>
  );
}
```

</scalar-tab>
<scalar-tab title="Button">

```tsx
import { usePresent } from "@plandalf/react";

export function UpgradeButton() {
  const { present, presenting } = usePresent();

  return (
    <button disabled={presenting} onClick={() => present("pro-plan")}>
      Upgrade
    </button>
  );
}
```

</scalar-tab>
<scalar-tab title="Identity">

```tsx
import { useEffect } from "react";
import { usePlandalf } from "@plandalf/react";

export function IdentifyUser({ userJwt }: { userJwt: string }) {
  const sdk = usePlandalf();

  useEffect(() => {
    sdk.identify(userJwt);
    return () => sdk.reset();
  }, [sdk, userJwt]);

  return null;
}
```

</scalar-tab>
</scalar-tabs>

## Related docs

- [React SDK](https://plandalf.com/docs/packages/react) — Review provider, hooks, gates, and direct SDK access.

- [Configure the SDK](https://plandalf.com/docs/sdk) — Use frame, mode, promo, identity, metadata, and continuity options.

- [Live events](https://plandalf.com/docs/packages/sdk/interfaces/FlowEvent) — React to checkout lifecycle updates from the app.

Source: https://plandalf.com/docs/product-guides/platforms/react-app
