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

# React Native quickstart

> Embed support in your RN app with a few method calls, on bare RN or Expo.

`@clariodesk/react-native` mirrors the [Flutter SDK](/flutter/quickstart) 1:1:
device-is-identity auth, live updates over Centrifugo/SSE, presence, read
receipts, typing, push, attachments, and CSAT. Two integration modes, one
install: headless methods, or the prebuilt `@clariodesk/react-native/ui` chat.

## Install

```sh theme={null}
npm install @clariodesk/react-native
# secure RNG (required); import once at app entry (see below)
npm install react-native-get-random-values
```

Then pick the secure-storage peer for your stack:

```sh theme={null}
npx expo install expo-secure-store   # Expo
npm install react-native-keychain    # bare RN
```

See [installation](/react-native/installation) for the Expo config plugin,
attachment pickers, and the full peer-dependency matrix.

## Headless quick start

```ts theme={null}
// At the very top of index.js, before anything else:
import 'react-native-get-random-values';

import { ClarioDesk } from '@clariodesk/react-native';

// 1. Once at app start. First launch generates the device key + registers;
//    later launches reuse it. Realtime defaults to Centrifugo, falls back to SSE.
await ClarioDesk.init({ apiKey: 'pk_live_…' });

// 2. After your own auth knows the user (metadata only; the device key is the
//    real identity, so this grants no access).
await ClarioDesk.identify({ externalId: user.id, email: user.email });

// 3. Writes are imperative + optimistic.
const { ticket } = await ClarioDesk.createTicket({ subject: '', body: 'Upload is broken' });
await ClarioDesk.sendMessage(ticket.id, 'Still happening on 1.4.2');

// 4. Reads are live. subscribe* returns an unsubscribe function.
const off = ClarioDesk.subscribeMessages(ticket.id, (messages) => render(messages));

// 5. On sign-out / user switch.
await ClarioDesk.reset();
```

## React hooks

Idiomatic state binding (not UI) lives in a separate entry so the core has no
React dependency:

```tsx theme={null}
import {
  useTickets, useMessages, useTyping, useAgentPresence,
  useConnection, useSync, usePushOpened,
} from '@clariodesk/react-native/hooks';

const { tickets, loading } = useTickets();
const { messages } = useMessages(ticketId);
const supportTyping = useTyping(ticketId);
const agentOnline = useAgentPresence();
const conn = useConnection(); // 'connecting' | 'connected' | 'reconnecting' | 'disconnected' | 'fatal'
```

A message with `pending: true` is optimistic ("sending…"); `failed: true` means
the send was rejected, so render tap-to-retry with `ClarioDesk.retryMessage(m)`.
An offline send stays `pending` and auto-flushes on reconnect (durable outbox).

<CardGroup cols={2}>
  <Card title="Installation & Expo" icon="box" href="/react-native/installation">
    Config plugin, dev build vs Expo Go, attachment pickers.
  </Card>

  <Card title="Prebuilt UI" icon="layout-panel-left" href="/react-native/prebuilt-ui">
    Drop-in themeable chat: `@clariodesk/react-native/ui`.
  </Card>
</CardGroup>
