smithery.ai

watermelondb

WatermelonDB models, observation patterns, and React integration. Use when writing or debugging model code, observers (findAndObserve, query.observe), or screens that display live-updating DB data.

First seen Apr 24, 2026

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 5,020 B
  • docs SUMMARY.md 217 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

WatermelonDB Model & Observation

Overview

This skill covers WatermelonDB models (database/models/), observation (reactive queries), and ensuring React re-renders when observed data changes. Use it when working with findAndObserve, query.observe(), withObservables, or any screen that subscribes to DB changes.


Observation & React Re-rendering

findAndObserve and same-reference emission

  • findAndObserve(id) (on a collection): Fetches a record by ID, returns an

Observable that emits immediately on subscribe and whenever the record is updated or deleted.

  • When a model is updated (e.g. via model.update() or @writer methods), the

observable emits the same object reference with updated properties — it does not emit a new model instance.

React useState bailout

  • useState uses Object.is to decide whether to re-render. Passing the **same

reference (e.g. setPhrase(model)) after an update means no re-render**.

  • Result: DB updates (text, note, language, etc.) don’t appear until the

user navigates away and back, when a new subscription yields a fresh reference.

Fix: store a wrapper so each emit is a new reference

When subscribing to a single model (e.g. findAndObserve) and storing it in React state, don’t store the raw model. Store a wrapper so every emission updates state with a new object:

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;
  • Use phrase (derived) everywhere in the component. Updates persisted to the

DB will re-emit, update phraseState with a new wrapper, and trigger a re-render.

Query observe() and arrays

  • query.observe() emits arrays of models. When the query result set

changes, WatermelonDB typically emits a new array reference, so setState(results) usually triggers re-renders.

  • If you build derived data (e.g. linked.filter(...), assignments) in

the subscribe callback and setState that, you’re already passing new references — no extra wrapper needed.


withObservables (HOC)

  • withObservables(triggerProps, getObservables) injects observable values

as props and always passes a new state object into setState (e.g. { values, isFetching }), so React re-renders on each emission even when model references are unchanged.

  • Use it when you can observe a model (or query) passed as a prop: e.g.

withObservables(['attempt'], ({ attempt }) => ({ attempt: attempt.observe(), ... })). See AttemptCard in features/lesson/components/AttemptCard.tsx.

  • For route params (e.g. id) you typically subscribe manually in

useEffect (e.g. findAndObserve(id)). In that case, use the wrapper pattern above instead of storing the raw model.


Model patterns in this project

  • Models: database/models/ (e.g. Phrase, Lesson, Attempt,

Translation, Deck). Use @field, @writer, and static helpers (e.g. Phrase.findOrCreatePhrase, Lesson.addLesson).

  • Observation: useDatabase() from @nozbe/watermelondb/react; then

collection.findAndObserve(id) or query.observe().subscribe(...).

  • Schema/tables: database/schema.ts; collection access via

db.collections.get<Model>(TABLE).


Quick reference

Scenario Pattern Re-render guarantee
Single model by id (e.g. detail screen) findAndObserve + wrapper state { model, _key } Yes
Query results (list) query.observe() + setState(results) or derived structures Yes (new array/refs)
Model passed as prop withObservables(['model'], ({ model }) => ({ model: model.observe() })) Yes (HOC uses new state shape)

Resources

findAndObserve, observe(), withObservables, model updates.

  • Project: PhraseDetailScreen, LessonDetailScreen, SetDetailScreen

(findAndObserve + wrapper); AttemptCard (withObservables).