mcpField
C
capacitor-react

capacitor-react

github.com/capawesome-team開発52992 回インストール1 週間前に更新
リポジトリ

capacitor-react について

ReactでCapacitorアプリを開発するためのスキルです。プロジェクトの分析やネイティブ機能の統合に加え、フック、状態管理、ルーティング、ライフサイクルの実装方法を案内します。

主な機能

  1. 01プロジェクト設定の自動検出
  2. 02ReactでのCapacitorプラグイン利用
  3. 03ネイティブ機能をカスタムフック化
  4. 04ディープリンクとライフサイクルの処理
  5. 05プラットフォーム別の描画と呼び出し

活用シーン

  1. 01既存のReactアプリへのCapacitor導入
  2. 02コンポーネントからの安全なネイティブプラグイン利用
  3. 03アプリ復帰やAndroidの戻るボタンへの対応

インストール

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

$npx skills add https://github.com/capawesome-team/skills --skill capacitor-react

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

同梱ファイルreferences/custom-hooks.mdreferences/plugin-usage-patterns.md

詳細

Capacitor React

React で Capacitor アプリを開発するための、プロジェクト構成、フック、状態管理、ネイティブデバイス機能にアクセスする React 固有のパターンです。

前提条件

  1. React を使用する Capacitor 6、7、または 8 のアプリ。
  2. Node.js と npm がインストールされていること。
  3. React 18 以降。
  4. iOS の場合:Xcode がインストールされていること。
  5. Android の場合:Android Studio がインストールされていること。

エージェントの動作

  • 質問する前に自動検出します。 プロジェクトの package.json にある依存関係(react、react-dom、@capacitor/core)、プラットフォーム(android/、ios/)、ビルドツール(vite.config.ts、next.config.js、webpack.config.js)、TypeScript の使用状況を確認します。検出できない場合にのみユーザーに質問してください。
  • 手順を追って案内します。 一度に 1 つずつ、ユーザーに手順を説明します。関連のない複数の質問を一度に提示しないでください。
  • プロジェクトに合わせます。 既存のコードスタイル(関数コンポーネントかクラスコンポーネントか、TypeScript か JavaScript か、CSS Modules か styled-components か)を検出し、それに合ったコードを生成します。

手順

ステップ 1:プロジェクトを分析する

プロジェクトファイルを読み取り、次の項目を自動検出します。

  1. フレームワークの種類:package.json の依存関係と設定ファイル(vite.config.ts、next.config.js、remix.config.js)を調べて、通常の React アプリ(Vite/CRA)、Next.js、Remix のいずれかを確認します。
  2. Capacitor のバージョン:package.json から @capacitor/core のバージョンを読み取ります。
  3. React のバージョン:package.json から react のバージョンを読み取ります。
  4. TypeScript:tsconfig.json が存在するか、.tsx ファイルが使用されているかを確認します。
  5. プラットフォーム:どのディレクトリ(android/、ios/)が存在するかを確認します。
  6. Capacitor の設定形式:プロジェクトが capacitor.config.ts と capacitor.config.json のどちらを使用しているかを確認します。
  7. 状態管理:package.json で redux、@reduxjs/toolkit、zustand、jotai、@tanstack/react-query などが使用されているかを確認します。
  8. ルーター:package.json で react-router-dom、@tanstack/react-router などが使用されているかを確認します。
ステップ 2:プロジェクト構成

標準的な Capacitor React プロジェクトは、次の構成に従います。

project-root/
├── android/                  # Android native project (generated by Capacitor)
├── ios/                      # iOS native project (generated by Capacitor)
├── public/
├── src/
│   ├── components/           # Reusable UI components
│   ├── hooks/                # Custom React hooks (including native feature hooks)
│   ├── pages/                # Page/route components
│   ├── services/             # Service modules for Capacitor plugin calls
│   ├── App.tsx               # Root component
│   └── main.tsx              # Entry point
├── capacitor.config.ts       # Capacitor configuration
├── package.json
├── tsconfig.json
└── vite.config.ts            # Or other bundler config

プロジェクトがこの構成に従っていない場合は、実際のディレクトリ構成に合わせてすべての案内を調整します。ユーザーから明示的に依頼されない限り、プロジェクトを再構成しないでください。

ステップ 3:React で Capacitor プラグインを使用する

React コンポーネントやフックで Capacitor プラグインを使用する詳細なパターンについては、references/plugin-usage-patterns.md を読んでください。

主な原則:

  1. プラグインを直接インポートする — Capacitor プラグインは ES モジュールとしてインポートします。
  2. イベントハンドラーまたはエフェクト内でプラグインのメソッドを呼び出す — モジュールのトップレベルでは呼び出さないでください。
  3. リスナーには useEffect を使用する — useEffect 内で Capacitor のイベントリスナーを登録し、クリーンアップします。
  4. 呼び出す前にプラットフォームを確認する — プラットフォーム固有の呼び出しを保護するには、Capacitor.isNativePlatform() または Capacitor.getPlatform() を使用します。
ステップ 4:ネイティブ機能用のカスタムフック

Capacitor プラグインをラップする再利用可能なカスタムフックのパターンについては、references/custom-hooks.md を読んでください。

カスタムフックはネイティブ機能へのアクセスをカプセル化し、React の慣習に沿った API を提供します。ユーザーが複数のコンポーネントからネイティブ機能にアクセスする必要がある場合は、src/hooks/(またはプロジェクトでフックを管理している場所)にカスタムフックを作成してください。

ステップ 5:ネイティブデータを使った状態管理

プロジェクトで状態管理ライブラリを使用している場合は、次のようにネイティブデータを統合します。

  1. React Query / TanStack Query:Capacitor プラグインを呼び出すクエリ関数を使用します。これは、ネイティブ API から取得するデータ(デバイス情報、連絡先、ファイルシステムの読み取りなど)に適しています。
  2. Redux / Zustand / Jotai:Capacitor プラグインのコールバックからアクションをディスパッチするか、アトムを更新します。ネイティブ API の呼び出しはアクションクリエーターまたはサービスモジュールに置き、リデューサーやストアには置かないでください。
  3. 状態管理ライブラリを使用していない場合:React コンテキスト、または useState/useReducer を使ったカスタムフックで、コンポーネント間のネイティブデータ共有を行います。

ユーザーの要件で必要とされない限り、状態管理ライブラリの追加を推奨しないでください。

ステップ 6:ナビゲーションとディープリンク

プロジェクトで react-router-dom や別のルーターを使用している場合:

  1. ディープリンク:ルートコンポーネント内の useEffect、または専用のフックで、@capacitor/app プラグインの appUrlOpen イベントを監視するリスナーを登録します。ルーターの useNavigate() フックを使ってプログラムから遷移します。
import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { App, URLOpenListenerEvent } from '@capacitor/app';

const useDeepLinks = () => {
  const navigate = useNavigate();

  useEffect(() => {
    const listener = App.addListener('appUrlOpen', (event: URLOpenListenerEvent) => {
      const path = new URL(event.url).pathname;
      navigate(path);
    });

    return () => {
      listener.then(handle => handle.remove());
    };
  }, [navigate]);
};
  1. 戻るボタンの処理(Android):Android のハードウェア戻るボタンの押下を処理するため、@capacitor/app プラグインの backButton イベントを監視するリスナーを登録します。
import { useEffect } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { App } from '@capacitor/app';

const useBackButton = () => {
  const navigate = useNavigate();
  const location = useLocation();

  useEffect(() => {
    const listener = App.addListener('backButton', ({ canGoBack }) => {
      if (canGoBack) {
        navigate(-1);
      } else {
        App.exitApp();
      }
    });

    return () => {
      listener.then(handle => handle.remove());
    };
  }, [navigate, location]);
};
ステップ 7:プラットフォーム固有のレンダリング

Capacitor.getPlatform() または Capacitor.isNativePlatform() を使用して、コンポーネントのレンダリングやプラットフォーム固有の動作を条件分岐します。

import { Capacitor } from '@capacitor/core';

const MyComponent: React.FC = () => {
  const platform = Capacitor.getPlatform(); // 'ios' | 'android' | 'web'
  const isNative = Capacitor.isNativePlatform();

  return (
    <div>
      {platform === 'ios' && <IOSSpecificComponent />}
      {platform === 'android' && <AndroidSpecificComponent />}
      {!isNative && <WebFallbackComponent />}
    </div>
  );
};

プラットフォームの判定を再利用する場合は、ユーティリティまたはフックを作成します。

import { Capacitor } from '@capacitor/core';

export const usePlatform = () => {
  return {
    platform: Capacitor.getPlatform(),
    isNative: Capacitor.isNativePlatform(),
    isIOS: Capacitor.getPlatform() === 'ios',
    isAndroid: Capacitor.getPlatform() === 'android',
    isWeb: Capacitor.getPlatform() === 'web',
  };
};
ステップ 8:ライフサイクルとアプリの状態

@capacitor/app プラグインを使用して、React でアプリのライフサイクルイベントに対応します。

import { useEffect } from 'react';
import { App } from '@capacitor/app';

const useAppState = (onResume?: () => void, onPause?: () => void) => {
  useEffect(() => {
    const resumeListener = App.addListener('resume', () => {
      onResume?.();
    });

    const pauseListener = App.addListener('pause', () => {
      onPause?.();
    });

    return () => {
      resumeListener.then(handle => handle.remove());
      pauseListener.then(handle => handle.remove());
    };
  }, [onResume, onPause]);
};

これを使って、アプリがフォアグラウンドに戻ったときにデータを更新したり、メディアを一時停止したり、アプリがバックグラウンドに移行するときに状態を保存したりできます。

ステップ 9:ビルドと実行

変更を実装した後:

npm run build
npx cap sync
npx cap run android
npx cap run ios

ライブリロードを使って開発する場合:

npx cap run android --livereload --external
npx cap run ios --livereload --external

--external フラグを指定すると、デバイスまたはエミュレーターから開発サーバーにアクセスできるようになります。--livereload フラグを指定すると、ソースファイルの変更時に自動で再読み込みされます。

エラー処理

  • 実行時にプラグインが見つからない:プラグインのインストール後に npx cap sync を実行したことを確認します。プラグインが package.json の依存関係に記載されていることを確認します。
  • Capacitor is not defined:@capacitor/core パッケージをインストールする必要があります。npm install @capacitor/core を実行します。
  • ネイティブメソッドが Web で失敗する:ネイティブ専用の呼び出しは Capacitor.isNativePlatform() でガードします。多くのプラグインには Web 用の実装がありますが、一部(例:ネイティブ UI を使う @capacitor/camera)は iOS/Android でのみ動作します。
  • イベントリスナーによるメモリリーク:必ず useEffect からクリーンアップ関数を返し、その中でリスナーハンドルの remove() を呼び出します。これを怠ると、再レンダリングのたびにリスナーが重複して登録されます。
  • イベントリスナー内の古いクロージャー:Capacitor のイベントリスナーが時間とともに変化する React の状態を参照する場合は、useRef を使って最新の値を保持するか、状態変数を useEffect の依存配列に追加してリスナーを登録し直します。
  • ライブリロードが接続されない:デバイスと開発マシンが同じネットワーク上にあることを確認します。npx cap run で --external フラグが使われていることを確認します。ファイアウォールが開発サーバーのポートをブロックしていないか確認します。
  • Web ではビルドできるがネイティブでは失敗する:Capacitor の代替手段を使わずに、ブラウザー専用 API(window.localStorage、navigator.geolocation)を使用していないか確認します。代わりに Capacitor プラグイン(@capacitor/preferences、@capacitor/geolocation)を使用します。
  • React の Strict Mode による二重マウント:開発環境では、React 18 の Strict Mode によってコンポーネントが 2 回マウントされます。これにより、Capacitor のイベントリスナーが重複することがあります。クリーンアップ関数でリスナーが正しく削除されることを確認してください。二重マウントの動作によって、クリーンアップが正しく機能するか検証できます。

関連スキル

  • ionic-react — @ionic/react を使うアプリ向けの Ionic Framework 固有の React パターン(IonReactRouter、ライフサイクルフック、オーバーレイフック)。
  • capacitor-angular — Capacitor アプリ開発における Angular 固有のパターンとベストプラクティス。
  • capacitor-app-upgrades — Capacitor アプリを新しいメジャーバージョンにアップグレードします。
  • capacitor-plugins — 公式およびコミュニティのソースから Capacitor プラグインをインストール、設定、使用します。
  • capacitor-push-notifications — Capacitor アプリで Firebase Cloud Messaging を使ったプッシュ通知を設定します。

コメント