# アプリに更新機能を組み込む

ルートコンポーネントへのProvider追加、更新チェック、ダウンロードと適用のタイミング、画面への状態表示を設定します。

## ルートコンポーネントを接続する {#basic}

[ネイティブ環境の設定](/docs/getting-started)後、ルートコンポーネントをProviderでラップし、プラットフォームに対応する `appKey` を指定します。

```tsx title="Root.tsx"
import { Pakta, UpdateProvider } from 'rn-update';
import App from './App';

const client = new Pakta({
  appKey: 'YOUR_PLATFORM_APP_KEY',
  updateStrategy: 'silentAndLater',
});

export default function Root() {
  return (
    <UpdateProvider client={client}>
      <App />
    </UpdateProvider>
  );
}
```

標準の RN アプリの場合、既存のアプリケーション名を使用してルートを登録します。

```tsx title="index.js"
import { AppRegistry } from 'react-native';
import { name as appName } from './app.json';
import Root from './Root';

AppRegistry.registerComponent(appName, () => Root);
```

Expo Router の場合は、既存の `Stack` または `Slot` を `app/_layout.tsx` でラップします。繰り返しの初期化を避けるために、プロセスごとに 1 つのプロバイダーをマウントし、コンポーネントの外側にクライアントを作成します。

### 複数のプラットフォーム キー {#platform-key}

複数のプラットフォームを出荷する場合にのみ、プラットフォームの選択を追加します。 CLI `selectApp` は、各プラットフォームの `appId` および `appKey` を `update.json` に書き込みます。まず各アプリケーションを選択し、これを単一プラットフォーム キーの代わりに使用します。

```tsx title="Read platform configuration"
import { Platform } from 'react-native';
import updateConfig from './update.json';

const platform = Platform.OS;
const configs = updateConfig as Record<string, { appKey: string }>;
const appKey = configs[platform]?.appKey;
if (!appKey) throw new Error(`Missing Pakta appKey for ${platform}`);
```

インポートされた JSON はアプリバンドルの一部になります。アプリケーション識別子のみを保持し、`PAKTA_API_TOKEN` は保持しないでください。

## バージョンを表示 {#use-update}

このコンポーネントをプロバイダー内でレンダリングします。空の `currentHash` は、埋め込みバンドルを示します。

```tsx title="UpdateStatus.tsx"
import { Button, Text, View } from 'react-native';
import { useUpdate } from 'rn-update';

export function UpdateStatus() {
  const { packageVersion, currentHash, lastError, checkUpdate } = useUpdate();
  return (
    <View>
      <Text>Pakta demo A</Text>
      <Text>Native: {packageVersion}</Text>
      <Text>Update: {currentHash || 'embedded'}</Text>
      <Button title="Check update" onPress={() => { void checkUpdate(); }} />
      {lastError ? <Text>{lastError.message}</Text> : null}
    </View>
  );
}
```

## 更新をいつ有効化するか選択する {#update-strategy}

|戦略 |経験 |使用例 |
| --- | --- | --- |
| `silentAndLater` |バックグラウンドでダウンロード、後で起動するとアクティベーション |このチュートリアルと中断のないセッション |
| `silentAndNow` |ダウンロードが完了したらすぐにリロード |中断が許容されるフロー |
| `alertUpdateAndIgnoreError` | 更新を促し、更新チェック時のエラーは無視します | SDK の既定値 |
| `alwaysAlert` |更新とエラーを表示 |内部診断 |

`checkStrategy` のデフォルトは `both` (開始および再開) です。他の値は `onAppStart` および `onAppResume` です。 `null` は JS 自動チェックを無効にします。ネイティブのコールド スタート チェックでは、引き続きアップデートがダウンロードされる場合があります。すべての更新機能が無効になるわけではありません。

## 手動更新 {#manual}

カスタム更新ボタンの場合、`checkStrategy: null` を設定し、プロバイダー内で次のメソッドを読み取ります。

```tsx
const { client } = useUpdate();

async function onUpdate() {
  if (!client) return;
  const info = await client.checkUpdate();
  if (!info?.update) return;
  const hash = await client.downloadUpdate(info);
  if (hash) await client.switchVersion(hash);
}
```

操作中の繰り返しクリックを無効にし、捕捉されたエラーを表示します。 `useUpdateProgress()` はダウンロードの進行状況を返します。進行状況が存在する場合、その範囲は 0 ～ 100 です。

## 健康状態の確認と回復 {#health}

プロバイダーは通常、1000 ミリ秒後に健全性を確認します。重要な初期化に時間がかかる場合は、次のオプションを既存のクライアントに追加します。

```tsx title="Delay health confirmation"
autoMarkSuccessDelayMs: 5000,
healthCheck: () => myCriticalModulesReady(),
```

アプリケーションの準備状況を使用して `myCriticalModulesReady` を実装します。 `false` を返すかスローすると、その確認がスキップされます。完全に制御するには、`autoMarkSuccess: false` を使用し、重要な画面の準備ができたら `useUpdate().markSuccess()` を呼び出します。

ネイティブ保護は、起動に失敗した後に未確認の更新をロールバックできます。ヘルス確認後の任意のエラーが必ずしもロールバックをトリガーするとは限りません。ネイティブ リカバリには、ネットワーク アクセス、有効な構成、および利用可能な修復展開が必要です。

## 拡張機能 {#hooks}

- フックを確認、ダウンロード、リロードします: [ClientOptions](/docs/api#client-options)。
- テスト用 QR コードでは `useUpdate().parseTestQrCode(code)` を使います。本番ビルドでは `testChannel: false` を設定できます。詳しくは[テストチャンネル](/docs/integration#test-channel)を参照してください。
- エラーを更新 ID と関連付けます: [エラー診断](/docs/errors)。

## テストチャンネル {#test-channel}

テスト QR コードはテスト更新を選択します。これは、ネイティブ パッケージの固定配布チャネルとは別のものです。最初のチュートリアルでは、スキャンを行わずに通常のデフォルト チャネル展開を使用します。必要な場合にのみスキャナーを追加し、それを許可するビルドを制御します。

## 次のステップ {#next}

このリリース パッケージを保持し、[最初のアップデート ](/docs/publish) を公開し、`Pakta demo A` を `Pakta demo B` に変更します。

[完了ボタン、エラーと進行状況の例](/docs/api#custom-update)。
