> For the complete documentation index, see [llms.txt](https://docs.tiun.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tiun.io/sdk/react-native-sdk/hooks.md).

# Hooks and events

The SDK exposes two hooks. `useTiun()` gives you the current state and the actions; `useTiunEvent()` subscribes to state changes as they happen. Both must be used inside [`<TiunProvider>`](/sdk/react-native-sdk/configuration.md) — they throw otherwise.

```tsx
import { useTiun, useTiunEvent } from '@tiun/react-native-sdk';

function Account() {
  const { user, isAuthenticated, login, logout } = useTiun();

  useTiunEvent('login', ({ user }) => {
    console.log('signed in as', user?.email);
  });

  // ...
}
```

***

## `useTiun()`

### State

| Property          | Type               | Description                                                                                                                                         |
| ----------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `isAuthenticated` | `boolean`          | Whether the user has a valid session.                                                                                                               |
| `user`            | `TiunUser \| null` | The current user, or `null` when signed out.                                                                                                        |
| `ready`           | `boolean`          | Whether the snippet has initialized and is ready for commands.                                                                                      |
| `cryptoOk`        | `boolean \| null`  | Whether the WebView can use the crypto the session depends on. `null` until it reports in; `false` means authentication cannot work on this device. |

### Actions

| Method                       | Returns                   | Description                                                    |
| ---------------------------- | ------------------------- | -------------------------------------------------------------- |
| `login()`                    | `void`                    | Open the login overlay.                                        |
| `logout()`                   | `void`                    | Clear the session and the stored device credentials.           |
| `checkout(options?)`         | `void`                    | Open checkout. Pass `{ productId }` to buy a specific product. |
| `getUserVerificationToken()` | `Promise<string \| null>` | Get a signed token for server-side verification.               |

{% hint style="info" %}
**You don't have to wait for `ready`.** `login()`, `logout()`, and `checkout()` are queued while the snippet is starting up and run as soon as it's ready, so wiring them straight to a button is safe. Use `ready` when you want to show a loading state instead.
{% endhint %}

### `checkout(options?)`

```tsx
const { checkout } = useTiun();

checkout({ productId: 'p-live-pro' });
```

The overlay collects the user's email, handles identity verification, takes payment, and grants access in one flow. On success the user's `productAccess` updates and `userChange` fires. For what happens behind the overlay, see [Checkout / How it works](/reference/checkout/how-it-works.md) in Reference.

### `getUserVerificationToken()`

Returns a signed JWT, valid for five minutes, that your backend exchanges for the verified user object. It resolves `null` when the user isn't signed in, or if tiun doesn't answer within five seconds.

```tsx
const { getUserVerificationToken } = useTiun();

async function loadProtectedData() {
  const token = await getUserVerificationToken();
  if (!token) return null;

  const response = await fetch('https://api.example.com/protected', {
    headers: { Authorization: `Bearer ${token}` },
  });

  return response.ok ? response.json() : null;
}
```

The server side is identical to the web SDK — see [verify authentication server-side](/guides/authentication/verify-server-side.md).

***

## `useTiunEvent(event, handler)`

Subscribe to a tiun event. The subscription is removed automatically when the component unmounts, and the handler is always the latest one you passed — you don't need to memoize it.

```tsx
useTiunEvent('userChange', ({ isAuthenticated, user }) => {
  setUser(user);
});
```

### Event reference

| Event        | Payload                                                  | Description                                                       |
| ------------ | -------------------------------------------------------- | ----------------------------------------------------------------- |
| `ready`      | —                                                        | The snippet has initialized and is ready to use.                  |
| `userChange` | `{ isAuthenticated: boolean, user: TiunUser \| null }`   | User state changed — session restore, login, checkout, or logout. |
| `login`      | `{ user: TiunUser \| null }`                             | The user signed in.                                               |
| `logout`     | —                                                        | The session was cleared.                                          |
| `error`      | `{ code?: string, message?: string, details?: unknown }` | An error occurred.                                                |

{% hint style="warning" %}
**`userChange` carries no `event` field here.** The web SDK's payload includes `event: 'init' | 'login' | 'checkout' | ...`; the React Native payload does not. Treat `userChange` as "the user state changed, re-read `user`", and use the separate `login` and `logout` events when you need to know which transition happened.
{% endhint %}

`userChange` is the event to build on: it fires on the initial session restore as well as on every later change, so a single handler keeps your UI in sync from launch onwards.

### `error`

```tsx
useTiunEvent('error', (err) => {
  console.warn('[tiun]', err.code, err.message);
});
```

`err.code` is a string, but there is no published enum of values and codes can change between versions. Show `err.message` to users and log `err.code` for support rather than branching on specific codes.

***

## `TiunUser`

| Field           | Type       | Description                              |
| --------------- | ---------- | ---------------------------------------- |
| `userId`        | `string`   | Stable identifier for this user in tiun. |
| `email`         | `string`   | Email on the account.                    |
| `productAccess` | `string[]` | Product IDs the user is entitled to.     |

`productAccess` is the source of truth for what a user can access — check against it rather than tracking entitlements yourself:

```tsx
const { user } = useTiun();
const hasPro = user?.productAccess.includes('p-live-pro') ?? false;
```

For how the array is populated and when it changes, see [User object](/reference/authentication/user-object.md) and [Product access](/reference/checkout/product-access.md) in Reference.

***

For these pieces assembled into working screens, see the [React Native examples](/sdk/react-native-sdk/examples.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.tiun.io/sdk/react-native-sdk/hooks.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
