meteor-react について
meteor-react は、Meteor 3 アプリで React インターフェースを構築するためのスキルです。リアクティブデータ用フック、描画、ビルド設定、更新処理、ブラウザテストを案内します。
主な機能
- 01React ルートのマウント
- 02react-meteor-data フックの選択
- 03Tracker 対応のリスト表示
- 04Suspense と非同期データの扱い
- 05Rspack 設定と React Refresh
- 06UI 動作のブラウザテスト
活用シーン
- 01Meteor 3 の React アプリを新規作成
- 02購読状態に応じた画面表示
- 03リアクティブなタスクリストの実装
- 04Meteor UI のブラウザテスト
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ meteor/ agent-skills --skill meteor-reactインストール後、Claude Code で/meteor-reactを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/build-refresh-and-testing.mdeval-cases.mdreact-meteor-data.mdsuspense-and-async.md詳細
Meteor 3 向け React インターフェース
React はレンダリングとローカル UI 状態を管理し、Meteor はリアクティブデータとビルドの受け渡しを管理します。コンポーネントは認可済みデータを利用し、メソッドを呼び出します。 パブリケーションとメソッドは引き続きサーバー側が権限を持ちます。
判断フロー
- 新しい JavaScript アプリの場合は、
meteor create --react <name>を実行します。React はデフォルトのスケルトンでもあります。TypeScript と TSX の場合は、meteor create --typescript <name>を実行します。 package.json、.meteor/packages、.meteor/versions、クライアントのエントリーポイント、rspack.config.*を確認します。スケルトンとreact-meteor-dataのバージョンは、それぞれ独立して変更される可能性があります。Meteor.startupからcreateRootを使って、React ルートを 1 つマウントします。- コンポーネントには、
react-meteor-dataのサーフェスを 1 つ選びます。- 明示的な読み込み UI と同期的な Minimongo の読み取りには、クラシックフックを使います。
- 保留中の状態とエラー状態を、上位の Suspense フォールバックと拒否境界がすでに管理している場合に限り、Suspense フックを使います。
- 準備状態には
useSubscribe、安定したドキュメント参照を持つリアクティブなリストにはuseFind、その他の Tracker 値にはuseTrackerを使います。 - React 固有の Rspack ルールはここで扱います。ルートエイリアス、ローダー、コード分割、キャッシュ、出力、移行に関する作業はビルドスキルに委ねます。
- UI の動作はブラウザーを使ったクライアントテストスイートでテストし、Tracker の計算処理やサブスクリプションを停止できるよう、レンダリングしたルートは必ずアンマウントします。
現在のスキャフォールド
meteor create --react my-app
cd my-app
meteor
現在の Meteor 3.4 以降のスキャフォールドでは、Rspack と react-meteor-data を使用します。.meteor/versions を確認してください。Meteor 3 では 3.0.0 以降が必要で、これらの例は 4.0.1 を対象としており、references/react-meteor-data.md に機能の最低バージョンが記載されています。
import { Meteor } from "meteor/meteor";
import { createRoot } from "react-dom/client";
import { App } from "/imports/ui/App";
import "/imports/ui/styles.css";
Meteor.startup(() => {
const container = document.getElementById("react-target");
if (!container) throw new Error("Missing #react-target");
createRoot(container).render(<App />);
});
TypeScript では client/main.tsx と tsconfig.json を使用し、通常は rspack.config.ts も使用します。Meteor はその TypeScript 設定を直接検出します。
リアクティブデータの選択
| 必要なもの | API | 契約 |
|---|---|---|
| サブスクリプションの準備状態 | クラシック useSubscribe | isLoading 関数を返します。呼び出して使用します。 |
| リアクティブなリスト | クラシック useFind | カーソルを返します。fetch() は使いません。 |
| ユーザー、件数、単一ドキュメント、ReactiveVar | クラシック useTracker | リアクティブな値を返します。任意の副作用は避けてください。 |
| Suspense を使った非同期値 | Suspense useTracker | 安定したキーと Promise を生成する関数を指定します。 |
| SSR 対応のコレクションクエリ | Suspense useFind | コレクションと find の引数タプルを渡します。 |
| 既存のクラスコンポーネント | withTracker | 対象を絞った保守中はそのまま維持し、フックへの移行は別途計画します。 |
クラシックなリストのスキャフォールド:
import { useFind, useSubscribe } from "meteor/react-meteor-data";
import { Tasks } from "/imports/api/tasks";
export function TaskList({ listId }) {
const isLoading = useSubscribe("tasks.byList", listId);
const tasks = useFind(
() => Tasks.find({ listId }, { sort: { createdAt: -1 } }),
[listId],
);
if (isLoading()) return <p>Loading...</p>;
if (tasks.length === 0) return <p>No tasks.</p>;
return <ul>{tasks.map((task) => <li key={task._id}>{task.title}</li>)}</ul>;
}
useFind はカーソルの監視を担い、変更されたドキュメント参照のみを更新します。変換済みの集計が明確な場合は useTracker を使います。依存関係や skipUpdate を調整する前に、references/react-meteor-data.md を読んでください。
Suspense と非同期リアクティビティ
Suspense のインポートではシグネチャが変わります。ドロップイン置換ではありません。
import { Suspense } from "react";
import { useFind, useSubscribe } from "meteor/react-meteor-data/suspense";
import { Tasks } from "/imports/api/tasks";
function TaskList({ listId }) {
useSubscribe("tasks.byList", listId);
const tasks = useFind(Tasks, [
{ listId },
{ sort: { createdAt: -1 } },
], [listId]);
return <ul>{tasks.map((task) => <li key={task._id}>{task.title}</li>)}</ul>;
}
export function TaskScreen({ listId }) {
return (
<AppErrorBoundary>
<Suspense fallback={<p>Loading...</p>}>
<TaskList listId={listId} />
</Suspense>
</AppErrorBoundary>
);
}
Suspense の useSubscribe は、サスペンド専用の呼び出しとして扱ってください。現在監査済みのパッケージでは、宣言された戻り値の型と実行時の値が一致しないため、戻り値を使用しないでください。安定したキー、拒否、SSR、await 後の Tracker.withComputation については、references/suspense-and-async.md を読んでください。
ビルドと更新の管理
Rspack はアプリの npm 依存関係から React を検出し、JSX または TSX の SWC パーサーを有効にして、クライアント開発用に React Refresh をインストールして注入します。通常の React Rspack アプリでは、更新プラグインを手動で追加する必要はありません。
rspack.config.* は最小限に保ってください。生成される JavaScript のひな形ではオプションの SVGR ルールを示し、TypeScript のひな形では型チェックを示しています。Meteor の SWC デフォルト設定を置き換えずに、@meteorjs/rspack の defineConfig を使ってカスタムルールを組み合わせてください。
React Compiler については、Meteor 3.6-beta.0 の組み合わせでは SWC がサポートされます。それ以前の組み合わせでは Babel を引き続き使用できます。React のバージョンターゲットとランタイム要件については、コンパイラーの設定を参照してください。
| リクエスト | 担当 |
|---|---|
| React の検出、JSX または TSX、React Refresh 境界 | このスキル |
rspack.config の一般的なヘルパー、SWC、エイリアス、キャッシュ、チャンク | meteor-modern-build-stack |
| 既存アプリまたはレガシーのビルドプラグインを Rspack に変換する | migrate-to-rspack |
Meteor-bundler の HMR またはカスタムの module.hot ライフサイクル | ビルドスキル。その後、React の症状についてはこのスキル |
編集によってページが再読み込みされたり、コンポーネントの状態がリセットされたりする場合は、まずモジュールをコンパイルしたバンドラーを特定してください。Rspack のクライアントグラフでは、React Refresh の境界を調べ、2 つ目の react-fast-refresh スタックを追加しないでください。Meteor-bundler のグラフでは、hot-module-replacement とバンドル済みの React Fast Refresh 統合を確認してください。references/build-refresh-and-testing.md を参照してください。
ミューテーションとテスト
イベントハンドラーから Meteor.callAsync を呼び出し、React の状態で保留中と拒否をモデル化し、バリデーションと認可はメソッド内に残してください。コンポーネントから機密コレクションに直接書き込まないでください。
テストでは、データを props として受け取るプレゼンテーションコンポーネントと、フックを所有するコンテナーを分離してください。前者はプロジェクト既存の React テストライブラリで単体テストします。後者は、制御可能な Minimongo または実際のパブリケーションを使用して、ブラウザーのクライアントでテストします。React は処理を破棄し、初期レンダリングロジックを複数回呼び出すことがあるため、リアクティブ関数の呼び出し回数ではなく、レンダリングされた動作を検証してください。
アンチパターン
- 従来の
isLoadingをブール値として扱うこと。これは関数なので、呼び出す必要があります。 Tasks.find().fetch()をuseFindに渡すこと。カーソルを返してください。useFindファクトリー内にサブスクリプションを入れること。サブスクライブは別に行ってください。useTrackerのリアクティブ関数内で、React の状態セッター、メソッド、分析処理、または任意の副作用を呼び出すこと。- すべての従来型コンポーネントに Suspense を強制すること。どちらの方式も引き続き有用です。
- 無関係なマウント済み計算に、汎用的な Suspense キーを再利用すること。
- 計算を復元せず、
awaitの後にのみ Tracker ソースを読み取ること。 - Meteor がすでに注入している場合に、プロジェクト設定へ
@rspack/plugin-react-refreshを追加すること。 - 1 つの React トランスフォームを追加するために、すべての Rspack SWC オプションを置き換えること。拡張してください。
- コンポーネントの統合テストですべての Meteor データ動作をモックで取り除くこと。