Skip to content

v2.1.0 — Selector-owned query loading

Choose a tag to compare

@Moon-DaeSeung Moon-DaeSeung released this 05 Aug 05:44
4171274

Selector-owned query loading

React components can now declare a query and its typed argument directly inside the existing useModel() / create() selector:

const products = useProduct((state) =>
  state.products.load({ page, filter })
)

const stats = useProduct((state) => state.stats.load())

The argument is inferred from Query<Data, Arg>. Calling .load() is the explicit opt-in; selecting the resource without it remains a passive read and never starts a request.

Behavior

  • reports first-load state during the initial render, avoiding the empty → skeleton flash before an effect runs
  • starts the request after React commits
  • changes cache keys when the serialized argument changes
  • does not restart a stable mounted query on unrelated rerenders
  • deduplicates concurrent selector loads for the same resource and key
  • supports single, infinite, and realtime resources
  • keeps call-time query options in imperative actions

Fully backward compatible

Existing action methods remain unchanged:

await this.model.products.query({ page, filter })
await this.model.products.refetch()
this.model.products.set(serverData)

useEffect-driven loading continues to work. Use selector .load() for view-owned requests and action .query() for commands, preloads, forced requests, multi-query workflows, and side effects. No additional React hook was added.

Documentation

  • rewrote llms.txt as a concise English domain implementation guide
  • documented selector-owned versus command-owned query loading
  • added cache-aware App Router Suspense fallback guidance using existing silent() + .set() initialization instead of a new hydration API
  • added the v2.1.0 release article

Validation

  • 25 test files, 345 tests passed
  • TypeScript and selector type-contract checks passed
  • ESM/CJS bundle and declaration generation passed
  • docs production build passed
  • published package tarballs were inspected

Packages

  • @comwit/state@2.1.0
  • comwit@2.1.0 compatibility shim → @comwit/state@^2.1.0

Closes #77. Implemented in #80.