---
title: "Present flows in Observer mode - React Native"
description: "Present flows and Paywall Builder paywalls in Observer mode in your React Native app while handling purchases with your own code."
---

If you've customized a flow or paywall using the builder, you don't need to worry about rendering it in your mobile app code to display it to the user. Such a flow or paywall contains both what should be shown and how it should be shown.

:::warning
This section refers to [Observer mode](observer-vs-full-mode) only. If you do not work in the Observer mode, refer to the [Display flows & paywalls](react-native-present-paywalls) topic.
:::

:::info
This capability requires Adapty React Native SDK 4.0 or later — previously it was available only in the native iOS and Android SDKs. See the [migration guide](migration-to-react-native-sdk-v4) to upgrade.
:::

<details>
   <summary>Before you start presenting flows (Click to Expand)</summary>

   1. Set up initial integration of Adapty [with the App Store](initial_ios) and [with Google Play](initial-android).
   2. Install and configure Adapty SDK. Make sure to set the `observerMode` parameter to `true`. Refer to the [React Native SDK installation guide](sdk-installation-reactnative).
   3. [Create products](create-product) in the Adapty Dashboard.
   4. [Configure flows or paywalls in the builders](create-paywall) and assign products to them.
   5. [Create placements and assign your flows or paywalls to them](create-placement).
   6. [Fetch flows and their configuration](react-native-get-pb-paywalls) in your mobile app code.

</details>

In Observer mode, the SDK does not make purchases for you. When a user taps the purchase or restore button in an Adapty-rendered flow or paywall, the SDK invokes your `onObserverPurchaseInitiated` or `onObserverRestoreInitiated` event handler instead — perform the purchase or restore with your own code there.

## Set the observer-mode event handlers

Unlike other platforms, there is no separate resolver object — the handlers are part of the regular [event handlers](react-native-handling-events-1), so set them on every flow you present.

<Tabs groupId="presentation-method" queryString>
<TabItem value="platform" label="React component" default>

For the React component, pass the handlers as props to `AdaptyFlowView`:

```typescript showLineNumbers title="React Native (TSX)"

function MyFlow({ flow }) {
  const onObserverPurchaseInitiated = useCallback<
    FlowEventHandlers['onObserverPurchaseInitiated']
  >((product, onStartPurchase, onFinishPurchase) => {
    onStartPurchase(); // the flow shows its loading indicator
    myPurchaseApi(product.vendorProductId)
      .then((transactionId) => adapty.reportTransaction(transactionId, flow.variationId))
      .finally(() => onFinishPurchase()); // the flow hides the loading indicator
  }, [flow]);

  const onObserverRestoreInitiated = useCallback<
    FlowEventHandlers['onObserverRestoreInitiated']
  >((onStartRestore, onFinishRestore) => {
    onStartRestore();
    myRestoreApi().finally(() => onFinishRestore());
  }, []);

  return (
    <AdaptyFlowView
      flow={flow}
      onObserverPurchaseInitiated={onObserverPurchaseInitiated}
      onObserverRestoreInitiated={onObserverRestoreInitiated}
      // ... your other event handlers
    />
  );
}
```

:::note
In the embedded component, the value a handler returns does not close the flow — unmount the component yourself after a successful purchase or restore.
:::

</TabItem>
<TabItem value="standalone" label="Modal presentation">

For modal presentation, set the handlers on the view you created:

```typescript showLineNumbers title="React Native (TSX)"

const view = await createFlowView(flow);

const unsubscribe = view.setEventHandlers({
  onObserverPurchaseInitiated(product, onStartPurchase, onFinishPurchase) {
    onStartPurchase(); // the flow shows its loading indicator
    myPurchaseApi(product.vendorProductId)
      .then((transactionId) => adapty.reportTransaction(transactionId, flow.variationId))
      .finally(() => onFinishPurchase()); // the flow hides the loading indicator
    return false; // keep the flow open; dismiss it yourself after success
  },
  onObserverRestoreInitiated(onStartRestore, onFinishRestore) {
    onStartRestore();
    myRestoreApi().finally(() => onFinishRestore());
    return false;
  },
});
```

</TabItem>
</Tabs>

The `onObserverPurchaseInitiated` handler informs you that the user has initiated a purchase, and `onObserverRestoreInitiated` — that the user has initiated a restore. Trigger your custom purchase or restore flow in response.

Also, remember to invoke the following callbacks to notify AdaptyUI about the process of the purchase or restore. This is necessary for proper flow behavior, such as showing the loader, among other things:

| Callback           | Description                                                                      |
| :----------------- | :------------------------------------------------------------------------------- |
| onStartPurchase()  | The callback should be invoked to notify AdaptyUI that the purchase is started.  |
| onFinishPurchase() | The callback should be invoked to notify AdaptyUI that the purchase is finished. |
| onStartRestore()   | The callback should be invoked to notify AdaptyUI that the restore is started.   |
| onFinishRestore()  | The callback should be invoked to notify AdaptyUI that the restore is finished.  |

## Present the flow

Present the flow as usual: [fetch the flow and create its view](react-native-get-pb-paywalls), then [present it](react-native-present-paywalls). No extra parameters are needed — the handlers fire only when the SDK was activated with `observerMode: true`.

:::warning
Don't forget to [report the transaction and associate it with the paywall](report-transactions-observer-mode-react-native). Otherwise, Adapty will not recognize the transaction and will not determine the source paywall of the purchase.
:::