mcpField
W
watermelondb

watermelondb

github.com/jchaselubitz開発049 回インストール37 週間前に更新
リポジトリ

watermelondb について

WatermelonDBを使ったデータベース連動型React画面の開発者向けに、モデルと監視クエリを解説するスキルです。通知時のオブジェクト参照が再レンダリングに与える影響と、購読や`withObservables`のパターンを示します。

主な機能

  1. 01`findAndObserve`でレコードを監視
  2. 02クエリ結果を購読
  3. 03Reactの参照比較による描画スキップを回避
  4. 04`withObservables`でリアクティブなプロパティを渡す

活用シーン

  1. 01レコード更新後に詳細画面を更新
  2. 02変化するクエリ結果からリストを描画
  3. 03監視対象のモデルをコンポーネントのプロパティに接続

インストール

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

$npx skills add https://github.com/jchaselubitz/drill-app --skill watermelondb

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

同梱ファイルmeta.yaml

詳細

WatermelonDB モデルと監視

概要

このスキルでは、WatermelonDB のモデル(database/models/)、監視 (リアクティブクエリ)、および監視対象のデータが変化したときに React を確実に再レンダリングする方法を扱います。findAndObserve、query.observe()、 withObservables を扱う場合や、DB の変更を購読する画面で使用します。


監視と React の再レンダリング

findAndObserve と同じ参照の発行
  • findAndObserve(id)(コレクション上):ID でレコードを取得し、購読時に即座に、またレコードが更新または削除されるたびに発行する Observable を返します。
  • モデルが更新されると(例:model.update() や @writer メソッドによる更新)、Observable は更新後のプロパティを持つ同じオブジェクト参照を発行します。新しいモデルインスタンスは発行しません。
React useState の更新スキップ
  • useState は、再レンダリングするかどうかの判断に Object.is を使用します。更新後に同じ参照(例:setPhrase(model))を渡すと、再レンダリングされません。
  • 結果:DB の更新(テキスト、メモ、言語など)は、ユーザーが画面を離れて戻り、新しい購読によって新しい参照が得られるまで表示されません。
修正方法:ラッパーを保存して、発行ごとに新しい参照にする

単一のモデル(例:findAndObserve)を購読して React の state に保存する場合、モデルそのものは保存しないでください。ラッパーを保存すると、発行のたびに state が新しいオブジェクトで更新されます。

const [phraseState, setPhraseState] = useState<
  { phrase: Phrase; _key: number } | null
>(null);

useEffect(() => {
  if (!id) return;
  const sub = db.collections
    .get<Phrase>(PHRASE_TABLE)
    .findAndObserve(id)
    .subscribe((result) => {
      setPhraseState({ phrase: result, _key: result.updatedAt });
    });
  return () => sub.unsubscribe();
}, [id, db]);

const phrase = phraseState?.phrase ?? null;
  • コンポーネント内では、派生した phrase をすべての箇所で使用します。DB に保存された更新が再発行されると、phraseState が新しいラッパーで更新され、再レンダリングがトリガーされます。
クエリの observe() と配列
  • query.observe() はモデルの配列を発行します。クエリ結果セットが変化すると、WatermelonDB は通常、新しい配列参照を発行するため、setState(results) で再レンダリングがトリガーされます。
  • 購読コールバック内で派生データ(例:linked.filter(...)、assignments)を作成して setState に渡す場合、すでに新しい参照を渡しているため、追加のラッパーは不要です。

withObservables(HOC)

  • withObservables(triggerProps, getObservables) は Observable の値を props として注入し、setState に常に新しい state オブジェクト(例:{ values, isFetching })を渡すため、モデルの参照が同じでも発行のたびに React が再レンダリングされます。
  • props として渡されたモデル(またはクエリ)を監視できる場合に使用します。例:withObservables(['attempt'], ({ attempt }) => ({ attempt: attempt.observe(), ... }))。features/lesson/components/AttemptCard.tsx の AttemptCard を参照してください。
  • ルートパラメーター(例:id)の場合は、通常 useEffect 内で手動で購読します(例:findAndObserve(id))。その場合、モデルそのものを保存せず、上記のラッパーパターンを使用してください。

このプロジェクトのモデルパターン

  • モデル:database/models/(例:Phrase、Lesson、Attempt、 Translation、Deck)。@field、@writer、および静的ヘルパー(例: Phrase.findOrCreatePhrase、Lesson.addLesson)を使用します。
  • 監視:@nozbe/watermelondb/react の useDatabase() を使用し、その後 collection.findAndObserve(id) または query.observe().subscribe(...) を使用します。
  • スキーマ/テーブル:database/schema.ts。コレクションには db.collections.get<Model>(TABLE) でアクセスします。

クイックリファレンス

シナリオパターン再レンダリングの保証
id で単一のモデルを取得する(例:詳細画面)findAndObserve + ラッパー状態 { model, _key }あり
クエリ結果(リスト)query.observe() + setState(results) または派生構造あり(新しい配列/参照)
プロパティとして渡されるモデルwithObservables(['model'], ({ model }) => ({ model: model.observe() }))あり(HOC が新しい状態の形を使用)

リソース

  • DeepWiki: Nozbe/WatermelonDB — findAndObserve、observe()、withObservables、モデルの更新。
  • プロジェクト: PhraseDetailScreen、LessonDetailScreen、SetDetailScreen (findAndObserve + ラッパー);AttemptCard(withObservables)。

コメント