# React app
Install Plandalf in a React app with checkout attributes, the browser SDK, or the React provider and hooks.
Source: /docs/platforms/react-app
Last modified: 2026-06-19
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.


> **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


### Load the SDK once


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


### Render a buying action


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


### Add identity only when needed


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


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


### React provider and hook


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

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

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

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

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

```tsx Identity
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;
}
```


## Related docs


### [React SDK](/docs/sdk/react)


    Review provider, hooks, gates, and direct SDK access.


### [Configure the SDK](/docs/sdk/configure)


    Use frame, mode, promo, identity, metadata, and continuity options.


### [Live events](/docs/sdk/events)


    React to checkout lifecycle updates from the app.