# Hooks
URL: /docs/react-native/hooks

Reactive hooks for accessing runtime state in React Native.

> For AI agents: a documentation index is available at [llms.txt](/llms.txt). Use `.md` for canonical markdown pages; `.mdx` is kept as a backwards-compatible alias on supported URL paths.

## State Hooks

### useAuiState

The primary hook for accessing reactive state. It accepts a selector function for fine-grained re-renders — the component only re-renders when the selected value changes (shallow equality).

```
import { useAuiState } from "@assistant-ui/react-native";

// Thread state
const messages = useAuiState((s) => s.thread.messages);
const isRunning = useAuiState((s) => s.thread.isRunning);
const isEmpty = useAuiState((s) => s.thread.isEmpty);

// Composer state
const text = useAuiState((s) => s.composer.text);
const composerIsEmpty = useAuiState((s) => s.composer.isEmpty);
const attachments = useAuiState((s) => s.composer.attachments);

// Message state (inside a message context)
const role = useAuiState((s) => s.message.role);
const isLast = useAuiState((s) => s.message.isLast);

// Thread list item state
const threadId = useAuiState((s) => s.threadListItem.id);
const title = useAuiState((s) => s.threadListItem.title);
```

### useAui

Access the store methods for imperative actions.

```
import { useAui } from "@assistant-ui/react-native";

const aui = useAui();

// Composer actions
aui.composer().setText("Hello");
aui.composer().send();

// Thread actions
aui.thread().cancelRun();
```

### useAuiEvent

Subscribe to events without causing re-renders.

```
import { useAuiEvent } from "@assistant-ui/react-native";

useAuiEvent("thread.modelContextUpdate", ({ threadId }) => {
  console.log("Model context updated:", threadId);
});
```

## Runtime Hooks

### useLocalRuntime

Create an `AssistantRuntime` with a `ChatModelAdapter`.

```
import { useLocalRuntime } from "@assistant-ui/react-native";

const runtime = useLocalRuntime(chatModel, {
  initialMessages: [],
});
```

| Option                    | Type                  | Description                                                           |
| ------------------------- | --------------------- | --------------------------------------------------------------------- |
| `initialMessages`         | `ThreadMessageLike[]` | Messages to pre-populate                                              |
| `maxSteps`                | `number`              | Maximum tool call steps per run                                       |
| `cloud`                   | `AssistantCloud`      | Optional cloud instance for persistence                               |
| `adapters`                | `object`              | Optional adapter overrides (see below)                                |
| `unstable_humanToolNames` | `string[]`            | Tool names that pause the run until a result is added via `addResult` |

The `adapters` option accepts the following fields (all optional):

| Adapter       | Type                     | Description                          |
| ------------- | ------------------------ | ------------------------------------ |
| `history`     | `ThreadHistoryAdapter`   | Load and save thread message history |
| `attachments` | `AttachmentAdapter`      | Handle file and attachment uploads   |
| `speech`      | `SpeechSynthesisAdapter` | Text-to-speech playback              |
| `dictation`   | `DictationAdapter`       | Speech-to-text input                 |
| `feedback`    | `FeedbackAdapter`        | Thumbs up/down feedback              |
| `suggestion`  | `SuggestionAdapter`      | Prompt suggestions                   |

### useRemoteThreadListRuntime

Create an `AssistantRuntime` with a persistent thread list backed by a `RemoteThreadListAdapter`. This wraps any runtime hook (such as one calling `useLocalRuntime` or a custom AI SDK hook) and layers thread-list management on top.

```
import { useRemoteThreadListRuntime } from "@assistant-ui/react-native";

const runtime = useRemoteThreadListRuntime({
  runtimeHook: () => useLocalRuntime(chatModel),
  adapter: myThreadListAdapter,
});
```

| Option         | Type                      | Description                                                                                  |
| -------------- | ------------------------- | -------------------------------------------------------------------------------------------- |
| `runtimeHook`  | `() => AssistantRuntime`  | Hook that returns a per-thread runtime                                                       |
| `adapter`      | `RemoteThreadListAdapter` | Backend adapter for listing/creating/archiving threads                                       |
| `allowNesting` | `boolean`                 | When `true`, silently becomes a no-op if already inside another `useRemoteThreadListRuntime` |

## Model Context Hooks

### Tools

Author tools in a `"use generative"` file with `defineToolkit`, the same API as on the web ([Defining Tools](/docs/tools/defining-tools)). The tool definition is forwarded to the model; when the model calls it, the `execute` function runs and the `render` component displays the result.

Add the [`@assistant-ui/metro`](https://www.npmjs.com/package/@assistant-ui/metro) plugin so Metro compiles the `"use generative"` directive:

```
const { getDefaultConfig } = require("expo/metro-config");
const { withAui } = require("@assistant-ui/metro");

module.exports = withAui(getDefaultConfig(__dirname));
```

```
"use generative";

import { defineToolkit } from "@assistant-ui/react-native";
import { Text, View } from "react-native";
import { z } from "zod";

export default defineToolkit({
  get_weather: {
    description: "Get the current weather for a city",
    parameters: z.object({ city: z.string() }),
    execute: async ({ city }) => {
      "use client";
      const res = await fetch(`https://api.weather.example/${city}`);
      return res.json();
    },
    render: ({ args, result }) => (
      <View>
        <Text>
          {args.city}: {result?.temperature}°F
        </Text>
      </View>
    ),
  },
});
```

```
import { AuiProvider, Tools, useAui } from "@assistant-ui/react-native";
import toolkit from "./weather-toolkit";

function ToolProvider({ children }: { children: React.ReactNode }) {
  const aui = useAui({ tools: Tools({ toolkit }) });
  return <AuiProvider value={aui}>{children}</AuiProvider>;
}
```

### useAssistantDataUI

Register a UI renderer for a named data message part.

```
import { useAssistantDataUI } from "@assistant-ui/react-native";

useAssistantDataUI({
  name: "weather_card",
  render: ({ data }) => (
    <View>
      <Text>{data.city}: {data.temperature}°F</Text>
    </View>
  ),
});
```

### useAssistantInstructions

Register system instructions in the model context.

```
import { useAssistantInstructions } from "@assistant-ui/react-native";

useAssistantInstructions("You are a helpful weather assistant.");
```

### useInlineRender

Wrap a tool UI component so that inline state updates (from a parent component's render) are reflected without remounting. Use this when the render function closes over props that change over time.

```
import { defineToolkit, useInlineRender } from "@assistant-ui/react-native";
import { Text } from "react-native";
import { useMemo } from "react";

export function useMyToolToolkit(someOuterProp: string) {
  const stableRender = useInlineRender(({ args, result }) => (
    <Text>{someOuterProp}: {result?.value}</Text>
  ));

  return useMemo(
    () =>
      defineToolkit({
        my_tool: {
          type: "backend",
          render: stableRender,
        },
      }),
    [stableRender],
  );
}
```

Import the toolkit hook, pass its result to `useAui({ tools: Tools({ toolkit }) })`, and provide the returned `aui` with `AuiProvider`, as shown in the [Tools](#tools) section above.

### makeAssistantDataUI

Create a component that registers a data UI renderer when mounted.

```
import { makeAssistantDataUI } from "@assistant-ui/react-native";

const WeatherCard = makeAssistantDataUI({
  name: "weather_card",
  render: ({ data }) => <Text>{data.city}: {data.temperature}°F</Text>,
});

<WeatherCard />
```

## Shared Providers

These context providers are re-exported from `@assistant-ui/core/react` and are used internally by the primitives to scope the `aui` store to a particular item (message, part, thread list item, etc.). They are available for advanced custom rendering scenarios.

### MessageByIndexProvider

Scopes the `aui` context to a specific message by its index in the thread.

```
import { MessageByIndexProvider } from "@assistant-ui/react-native";

<MessageByIndexProvider index={2}>
  {/* children can read s.message, s.composer */}
</MessageByIndexProvider>
```

### PartByIndexProvider

Scopes the `aui` context to a specific message part by its index.

```
import { PartByIndexProvider } from "@assistant-ui/react-native";

<PartByIndexProvider index={0}>
  {/* children can read s.part */}
</PartByIndexProvider>
```

### TextMessagePartProvider

Provides a synthetic text part context from a plain string. Useful for rendering text outside the normal message-part pipeline.

```
import { TextMessagePartProvider } from "@assistant-ui/react-native";

<TextMessagePartProvider text="Hello world" isRunning={false}>
  {/* children can read s.part as a text part */}
</TextMessagePartProvider>
```

| Prop        | Type      | Description                                           |
| ----------- | --------- | ----------------------------------------------------- |
| `text`      | `string`  | The text content                                      |
| `isRunning` | `boolean` | Whether the part is still streaming (default `false`) |

### ChainOfThoughtByIndicesProvider

Scopes the `aui` context to a slice of message parts that form a chain-of-thought block.

```
import { ChainOfThoughtByIndicesProvider } from "@assistant-ui/react-native";

<ChainOfThoughtByIndicesProvider startIndex={1} endIndex={3}>
  {/* children can read s.chainOfThought */}
</ChainOfThoughtByIndicesProvider>
```

### ChainOfThoughtPartByIndexProvider

Scopes the `aui` context to a specific part within a chain-of-thought block.

```
import { ChainOfThoughtPartByIndexProvider } from "@assistant-ui/react-native";

<ChainOfThoughtPartByIndexProvider index={0}>
  {/* children can read s.part */}
</ChainOfThoughtPartByIndexProvider>
```

### ThreadListItemByIndexProvider

Scopes the `aui` context to a specific thread list item by its index.

```
import { ThreadListItemByIndexProvider } from "@assistant-ui/react-native";

<ThreadListItemByIndexProvider index={0} archived={false}>
  {/* children can read s.threadListItem */}
</ThreadListItemByIndexProvider>
```

### SuggestionByIndexProvider

Scopes the `aui` context to a specific suggestion by its index.

```
import { SuggestionByIndexProvider } from "@assistant-ui/react-native";

<SuggestionByIndexProvider index={0}>
  {/* children can read s.suggestion */}
</SuggestionByIndexProvider>
```