mcpField
R
react-native

react-native

github.com/assistant-ui開発29983 回インストール2 日前に更新
リポジトリ

react-native について

react-native は、React Native でチャット UI を構築するための assistant-ui ランタイム連携プリミティブとスキルです。ネイティブ UI と AI SDK v7 のランタイムおよびトランスポートを組み合わせ、モデルルートは別のバックエンドで実行します。

主な機能

  1. 01スタイルなしの React Native プリミティブ
  2. 02AI SDK v7 ランタイムとトランスポート
  3. 03ネイティブのスレッドと入力欄の構成
  4. 04フロントエンドツールスキーマの転送
  5. 05ローカル永続化とスレッドアダプター
  6. 06Metro による生成ツールキット対応

活用シーン

  1. 01Expo アプリにチャット UI を構築する
  2. 02ネイティブアプリを別ホストのモデルルートに接続する
  3. 03ネイティブのメッセージ一覧と入力コントロールを構成する

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/assistant-ui/skills --skill react-native

インストール後、Claude Code で/react-nativeを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
adapters.md
custom-backend.md
hooks.md
migration.md
primitives.md

詳細

assistant-ui React Native

最新の API については、常に assistant-ui.com/llms.txt を参照してください。

@assistant-ui/react-native は、ランタイムに接続されたスタイル未適用の React Native プリミティブを提供します。これらを View、Text、Pressable、TextInput、FlatList、およびネイティブスタイルと組み合わせて使用し、チャット画面を構築します。@assistant-ui/ai-sdk は AI SDK v7 のランタイムとトランスポートを提供します。モデルのルートは別のバックエンドプロジェクトで実行され、Expo バンドル内で実行されることはありません。

目次

リファレンス

クイックスタート

メンテナンスされている Expo のサンプルから始めます。

npx assistant-ui@latest create --example with-expo my-app
cd my-app

アプリが到達できるエンドポイントを設定します。絶対 URL である必要があります。実機は、自身の localhost を開発サーバーに解決することはできません。

EXPO_PUBLIC_CHAT_ENDPOINT_URL="https://api.example.com/api/chat"

Expo を起動します。

npx expo start

手動セットアップ

既存の Expo アプリに、ネイティブランタイムとその AI SDK v7 のピアパッケージをインストールします。

npx expo install @assistant-ui/react-native @assistant-ui/ai-sdk ai@^7 @ai-sdk/react@^4

モデルのルートは別途ホストします。ネイティブアプリは AssistantChatTransport を通じて UI メッセージをそのルートに POST します。ルートはそれらを AI SDK v7 用に非同期で変換し、UI メッセージストリームを返します。

import { openai } from "@ai-sdk/openai";
import { convertToModelMessages, streamText } from "ai";

export async function POST(request: Request) {
  const { messages } = await request.json();
  const result = streamText({
    model: openai("gpt-5.6-luna"),
    messages: await convertToModelMessages(messages),
  });

  return result.toUIMessageStreamResponse();
}

フック内でランタイムを作成します。コンパイル済みのアプリが到達できるように、エンドポイントは公開 Expo 環境に保持してください。

import {
  AssistantChatTransport,
  useChatRuntime,
} from "@assistant-ui/ai-sdk";

const chatEndpoint = process.env.EXPO_PUBLIC_CHAT_ENDPOINT_URL;

export function useAppRuntime() {
  if (!chatEndpoint) {
    throw new Error("EXPO_PUBLIC_CHAT_ENDPOINT_URL is required");
  }

  return useChatRuntime({
    transport: new AssistantChatTransport({ api: chatEndpoint }),
  });
}

AssistantChatTransport はフロントエンドのツールスキーマとシステムメッセージを転送します。バックエンドがフロントエンドツールを有効にする場合、@assistant-ui/ai-sdk の frontendTools でリクエストツールを消費します。共有バックエンドの契約については tools を参照してください。

ネイティブチャットの構成

ランタイムをネイティブの AssistantRuntimeProvider の下に配置し、プリミティブからスレッドとコンポーザーを構成します。ThreadPrimitive.MessagesFlatList は現在のリストプリミティブであり、各行を対応するメッセージにスコープします。

import {
  AssistantRuntimeProvider,
  AuiIf,
  ComposerPrimitive,
  MessagePrimitive,
  ThreadPrimitive,
  useAuiState,
} from "@assistant-ui/react-native";
import { Text, View } from "react-native";
import { useAppRuntime } from "./use-app-runtime";

function MessageRow() {
  const role = useAuiState((s) => s.message.role);

  return (
    <View
      style={{
        alignSelf: role === "user" ? "flex-end" : "flex-start",
        backgroundColor: role === "user" ? "#007aff" : "#f0f0f0",
        borderRadius: 16,
        margin: 8,
        padding: 12,
      }}
    >
      <MessagePrimitive.Content />
    </View>
  );
}

function Composer() {
  return (
    <ComposerPrimitive.Root style={{ flexDirection: "row", gap: 8, padding: 12 }}>
      <ComposerPrimitive.Input
        multiline
        placeholder="Message..."
        style={{ borderWidth: 1, borderRadius: 20, flex: 1, padding: 10 }}
      />
      <ComposerPrimitive.Send>
        <Text>Send</Text>
      </ComposerPrimitive.Send>
    </ComposerPrimitive.Root>
  );
}

function ChatScreen() {
  return (
    <ThreadPrimitive.Root style={{ flex: 1 }}>
      <AuiIf condition={(s) => s.thread.isEmpty}>
        <Text style={{ padding: 16 }}>Send a message to begin.</Text>
      </AuiIf>
      <ThreadPrimitive.MessagesFlatList autoScroll>
        {() => <MessageRow />}
      </ThreadPrimitive.MessagesFlatList>
      <Composer />
    </ThreadPrimitive.Root>
  );
}

export default function App() {
  const runtime = useAppRuntime();

  return (
    <AssistantRuntimeProvider runtime={runtime}>
      <ChatScreen />
    </AssistantRuntimeProvider>
  );
}

MessagePrimitive.Content は、テキストパートをデフォルトでネイティブの Text として扱い、Markdown としては扱いません。モデルが Markdown を返す場合は、renderText を渡すか、React Native の Markdown レンダラーとともに MessagePrimitive.Parts を使用します。ネイティブのキーボード処理には、スレッドを KeyboardAvoidingView 内に配置し、プラットフォームに合わせて調整します。

プリミティブスコープ内でリアクティブな値には useAuiState を使用します。aui.composer.send() や aui.thread.cancelRun() などの命令的なアクションには、引数なしで useAui() を使用します。セレクターはプリミティブまたは安定した参照に留め、セレクター内でオブジェクトや配列を構築しないようにしてください。

ジェネレーティブツールキット

Metro は "use generative" で始まるファイルをコンパイルする必要があります。@assistant-ui/metro をインストールし、デフォルト設定をラップします。Expo は expo/metro-config から getDefaultConfig を取得し、素の React Native アプリは @react-native/metro-config から取得します。

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

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

バックエンドレスなツールキットの場合、aui オプションをラッパーを通じて渡し、フロントエンドおよびヒューマンツールのスキーマがアップロード可能なままになるようにします。

module.exports = withAui({
  ...getDefaultConfig(__dirname),
  aui: { backendless: true },
});

ツールキットは @assistant-ui/react-native に対して記述し、ネイティブの View および Text レンダラーを含めます。"use generative" ディレクティブにより、コンパイラーは execute からツールの種類を推論します。tools スキルでは、バックエンド、フロントエンド、ヒューマン、プロバイダー、外部、およびスタブツールのセマンティクスについて説明しています。

よくある落とし穴

モバイルアプリが /api/chat にポストしても、サーバーに到達しない

  • ネイティブアプリには、相対リクエストのためのブラウザオリジンがありません。EXPO_PUBLIC_CHAT_ENDPOINT_URL に完全なルート URL を設定してください。
  • シミュレーターまたは実機から到達可能なホストを使用してください。デバイスの localhost はデバイス自身を指します。

プロバイダーはマウントされているのに、プリミティブが例外を投げる、または状態が表示されない

  • useChatRuntime または他のサポートされているランタイムフックでランタイムを作成し、それを runtime={runtime} として AssistantRuntimeProvider に渡してください。
  • プリミティブはそのプロバイダーの下にレンダリングしてください。メッセージ、パート、添付ファイル、キュー、サジェスチョン、スレッドリスト項目のプリミティブには、それぞれ対応する親のレンダースコープも必要です。

Web の Thread または Elements のインポートが Expo アプリでレンダリングされない

  • shadcn Elements カタログは DOM と Tailwind ベースです。ネイティブ UI は @assistant-ui/react-native のプリミティブと React Native のスタイルで構築してください。

メッセージリストが最下部に留まらない

  • 新しい画面では、autoScroll を指定して ThreadPrimitive.MessagesFlatList を使用してください。ThreadPrimitive.Messages は互換性のために残されており、自動スクロールオプションはデフォルトで false です。

ツールキットが通常のモジュールとしてコンパイルされる、またはツールスキーマがモデルに到達しない

  • "use generative" を使用する前に、Metro に withAui を追加してください。
  • サーバービルドで同一の generative モジュールをインポートしてください。サーバービルドがない場合は、aui: { backendless: true } を設定してください。

Markdown がリテラルのアスタリスクやフェンスとして表示される

  • MessagePrimitive.Content はデフォルトでネイティブの Text を使用します。renderText を通じてネイティブの Markdown レンダラーを指定してください。

関連スキル

  • setup -- assistant-ui の Web プロジェクトの create、initialize、設定
  • primitives -- Web アプリケーション向けの DOM プリミティブであり、React Native UI 向けではありません
  • runtime -- ネイティブと共有されるランタイムの動作とバックエンドトランスポートの概念
  • tools -- generative ツールキット、そのバックエンドルート、カスタムツール UI

コメント