---
title: "React Native SDK"
description: "Install SeatLayer React Native 0.4.0 and choose a ready-made picker, branded flow, custom component layout, or typed raw map for Expo and Community CLI apps."
---

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

# React Native SDK

SeatLayer React Native `0.4.0` ships a complete native buyer picker for Expo and
React Native Community CLI applications. The package includes the ready-made
flow, a controlled modal, themes and locale strings, 62 style slots, 27
complete-part builders, public components for a host-owned layout, and the
preserved low-level `SeatLayerView` API.

> **React Native 0.4.0 on npm**
>
> `@seatlayer/react-native@0.4.0` supports React 18.2+, React Native 0.72+,
> and `react-native-webview` 13+, and includes ESM, CommonJS, and TypeScript
> declarations. Every integration level described here is part of that
> package version.

> **Upgrading from 0.3.x**
>
> `0.4.0` is a breaking release. The dense phone ticket list and the
> `From €X` peek line are gone: the cart shows one card per ticket.
> `SeatLayerPeekLine`, the checkout button's `peekLine`, `fromPriceText`,
> `totalText`, and `showPrices` inputs, the `denseLine*` style slots (now
> `cartCard*`), `strings.applyFilters`, `strings.accessNoneLeft` (use
> `notAvailable`), `onCartUndo`, and `SeatLayerBookButtonProps.compact` were
> removed. The dock bar is off by default on every width; set `showDockBar`
> to bring it back. See the
> [tagged changelog](https://github.com/seatlayer/seatlayer-react-native/blob/v0.4.0/CHANGELOG.md)
> for the full list.

## Install

### Expo

```bash
npm install @seatlayer/react-native@0.4.0
npx expo install react-native-webview
```
### Community CLI

```bash
npm install @seatlayer/react-native@0.4.0 react-native-webview
npx pod-install
```

React Native autolinks `react-native-webview` on iOS and Android. SeatLayer
ships no additional native module, pod, or manual linking step.

On iOS, the seat-note and accessibility icons need a vector renderer. Add the
optional `react-native-svg` peer and register it once at start-up:

```tsx
import Svg, { Circle, Path } from 'react-native-svg';
import { installSeatLayerPickerSvgIcons } from '@seatlayer/react-native';

installSeatLayerPickerSvgIcons({ Svg, Path, Circle });
```

Without it, iOS keeps the words and drops the icon beside them. Give the picker
a full-screen or otherwise bounded parent; the map cannot infer height from an
unbounded layout.

## Render the complete picker

Memoize the configuration with `useMemo`. A publishable key is appropriate
for Public inventory; private or audience-restricted inventory uses the
renewable provider shown below.

```tsx title="TicketPickerScreen.tsx"
import React, { useMemo } from 'react';
import { View } from 'react-native';
import {
  SeatLayerPicker,
  type SeatLayerConfiguration,
  type SeatLayerPickerCheckoutHandoff,
} from '@seatlayer/react-native';

export function TicketPickerScreen({ event }: { readonly event: string }) {
  const configuration = useMemo<SeatLayerConfiguration>(
    () => ({
      event,
      publicKey: '<YOUR_PUBLIC_KEY>',
      currency: 'USD',
      maxSelection: 8,
    }),
    [event],
  );

  const continueWithHandoff = async (
    handoff: SeatLayerPickerCheckoutHandoff,
  ) => {
    await checkoutBackend.begin({ holdId: handoff.holdId });
  };

  return (
    <View style={{ flex: 1 }}>
      <SeatLayerPicker
        configuration={configuration}
        themeMode="auto"
        onCheckout={continueWithHandoff}
      />
    </View>
  );
}
```

The default tree covers loading, live availability, price and accessibility
filters, venue/floor/section navigation, confirmation and ticket tiers, GA and
table quantities, a cart with one card per ticket, temporary holds, expiry recovery, 2D/3D and
panorama chrome, and one typed checkout handoff.

## Public and private inventory

For login-gated, presale, partner, channel, or other private inventory, omit
`publicKey` and provide renewable buyer access from your authenticated backend:

```tsx
const configuration = useMemo<SeatLayerConfiguration>(
  () => ({
    event,
    buyerAccessTokenProvider: ({ reason }) =>
      buyerBackend.mintSeatLayerAccess(reason),
  }),
  [event],
);
```

Mint the native buyer-access session through
[buyer access sessions](/server-api/buyer-access-sessions), return only its
short-lived token to the provider, and treat the SDK access context as opaque.
Tokens stay in memory. Never put a SeatLayer secret key in JavaScript, the app
bundle, a URL, a React key, an event payload, logs, or analytics.

## Choose an integration level

| Level | Entry point | Your application owns |
| --- | --- | --- |
| Complete screen | `SeatLayerPicker` | Route, configuration, callbacks, checkout destination |
| Controlled presentation | `SeatLayerPickerModal` | Visibility, barrier behavior, and dismissal |
| Branded flow | Picker + options, theme, strings, styles, builders | Brand and selected complete parts |
| Custom hierarchy | `SeatLayerPickerScope` + public components | The complete React Native layout |
| Raw map | `SeatLayerView` + `SeatLayerController` | Every buyer surface and hold transition |

All five paths use the same inventory source. The first four keep the native
picker's selection rules, hold ownership, lifecycle recovery, supported-feature
checks, and checkout handoff.

### Present it as a modal

```tsx
<SeatLayerPickerModal
  visible={isPickerOpen}
  configuration={configuration}
  onCheckout={continueWithHandoff}
  onRequestClose={() => setPickerOpen(false)}
  barrierDismissible
/>
```

The modal uses the same scope and semantic Back ladder as the in-page picker;
it does not create a second product surface.

### Brand or replace individual parts

```tsx
<SeatLayerPicker
  configuration={configuration}
  themeMode="dark"
  locale="fr-FR"
  options={{
    layout: 'adaptive',
    chrome: { priceLegend: false },
    haptics: true,
    languages: ['en-GB', 'fr-FR'],
  }}
  strings={{ holdAndCheckout: 'Continue' }}
  styles={{
    headerContainer: { backgroundColor: '#172033' },
    continueButton: { backgroundColor: '#5B4B8A' },
  }}
  builders={{ header: ({ defaultChild }) => defaultChild }}
  onCheckout={continueWithHandoff}
/>
```

Use options for behavior and visibility, theme roles for coordinated native/map
color, locale and strings for wording, style slots for aesthetic changes, and a
builder when a complete part needs different structure. Builders receive the
live scope and canonical child; they do not become inventory authority.

[See every integration layer and public component](/buyer-sdk/react-native/native-picker).

## Checkout and hold ownership

The picker selects and holds inventory. Your trusted backend inspects and books
the hold after payment or order validation.

1. `onCheckout` receives one opaque `SeatLayerPickerCheckoutHandoff`.
2. Send only `handoff.holdId` and your normal order context to the backend.
3. Inspect the hold and calculate payable totals from trusted server data.
4. Charge through your payment provider.
5. Reuse the same `bookingRef` so retries are idempotent.

Ordinary picker state deliberately omits the hold ID. Before a successful
handoff, the picker owns the hold and may release it on close. After your
callback accepts the handoff, your product owns booking, rejection/release, or
expiry. If the callback rejects, the SDK rejects that exact handoff and returns
the buyer to a recoverable picker state.

Read [holds and secure checkout](/buyer-sdk/holds-and-checkout) before wiring
payment.

## Application and SDK ownership

| React Native components own | SeatLayer SDK owns |
| --- | --- |
| Header, price/floor/section navigation, accessibility filters, confirmation, quantities, cart, hold state, checkout, loading/errors, Test Mode, required attribution, Back and adaptive presentation | Seats, labels, geometry, hit testing, pan/pinch, camera, authored venue 3D, and panorama pixels |
| Safe areas, app lifecycle, native component layout, haptics, and accessibility semantics | Authoritative inventory state and supported map capabilities |

Changing native presentation does not create another map or discard camera,
selection, or hold state.

## Lifecycle and recovery

The ready picker handles foreground synchronization, availability refresh,
hold-lapse recovery, viewport insets, and a deterministic Back ladder. Keep the
picker mounted for the screen lifecycle and keep configuration identity unchanged.

- A resumed app reconciles the server hold instead of trusting a paused timer.
- Seats sold while the app was away are removed through authoritative
  unavailable-object state.
- Repeated checkout taps join one flight.
- A rejected checkout remains recoverable in the picker.
- Unmount permanently ends that picker session.
- Restore a host-owned hold only when your checkout promises restoration.

Raw-map applications must implement these host responsibilities themselves;
see the [raw-map reference](/buyer-sdk/react-native/raw-map).

## Run the tagged example

```bash
git clone --branch v0.4.0 --depth 1 https://github.com/seatlayer/seatlayer-react-native.git
cd seatlayer-react-native
pnpm install
cd example
pnpm install
EXPO_PUBLIC_SEATLAYER_EVENT="<YOUR_EVENT_KEY>" \
  EXPO_PUBLIC_SEATLAYER_PUBLIC_KEY="<YOUR_PUBLIC_KEY>" \
  pnpm start
```

The Expo example mounts the ready-made picker and exercises the secure
checkout handoff. Validate real inventory, lifecycle, safe areas, rotation,
accessibility, 3D/panorama, and checkout on supported physical iOS and Android
devices before rollout.

## Product scope

React Native `0.4.0` accepts one published Event per picker. Native Performance
Group and Season configuration is not part of this release; use their browser
pickers until a native release documents those contracts.

## Next steps

- [Native picker, customization, and component composition](/buyer-sdk/react-native/native-picker)
- [Raw-map API](/buyer-sdk/react-native/raw-map)
- [Compare all four native SDKs](/buyer-sdk/mobile)
- [Secure checkout](/buyer-sdk/holds-and-checkout)
- [Troubleshooting matrix](/buyer-sdk/mobile#troubleshooting)
- [`v0.4.0` source](https://github.com/seatlayer/seatlayer-react-native/tree/v0.4.0)
- [Tagged example](https://github.com/seatlayer/seatlayer-react-native/tree/v0.4.0/example)
- [Tagged TypeScript exports](https://github.com/seatlayer/seatlayer-react-native/blob/v0.4.0/src/index.ts)
- [Tagged changelog](https://github.com/seatlayer/seatlayer-react-native/blob/v0.4.0/CHANGELOG.md)

Source: https://docs.seatlayer.io/buyer-sdk/react-native/index.mdx
