MATES / Docs

Patterns & Pitfalls

Do/don't index for Mates — link out to the mental model and each API's anti-patterns so you build the right habit once.

Why this page exists

Most Mates bugs come from putting work in the wrong execution context — creating atoms in the template, reading props once in setup, or nesting a second router. This page is a checklist, not a deep API reference. Start with Mental Model (four contexts), then use the links below when a specific API's warnings apply.

Mental model checklist

Four contexts: module (shared primitives), outer/setup (create once), inner/template (read + bind), handler (mutate). Full walkthrough: /docs/mental-model.

Question
Answer in Mates
Deep dive
Where does state live? Atoms / stores in outer scope or module atom, store
What triggers update? Reading atoms inside an active template Mental Model
How do I fetch data? asyncAction (or RPC on fullstack) asyncAction
How do I navigate? useUtils().navigateTo + one Router Router
How do I read :id? paramsAtom() after a match Path atoms
How do I nest screens? Conditionals on paramsAtom / qsAtom — not a second router Router
How do I block leave? onNavigationRequest + next(), or lockNavigation() Lock navigation
Where do side effects go? onMount, effect, eleHook, onNavigate onMount, effect

Do

  • Keep state in the outer component function — Mental Model, atom
  • Call propsFn() inside the inner template so props stay reactive — Props
  • Use derived atoms / memo for computed values — memo
  • Return cleanup from onMount when you subscribe — onMount
  • Use asyncAction for server data with loading UI — asyncAction
  • Colocate routes in one Router([...], NotFound) or animatedRouter; nest UI with paramsAtom() / qsAtom()Router
  • Navigate with useUtils().navigateTo — atom .set also navigates (optional replace) — navigate
  • Guard leave with onNavigationRequest — call next() to allow (AND across subscribers) — Lock navigation
  • Key large lists with repeat(items, key, row)Lists
  • Use mates-ui tokens for consistent design

Don't

  • Create atoms / call lifecycle hooks inside the render function — throws; see Mental Model and atom warnings
  • Destructure propsFn() in the outer function — freezes values — Props
  • Use effect to copy atom → atom when derivation / memo works — effect
  • Call async actions unconditionally each render — kick off from setup, mount, or events — asyncAction
  • Mutate props or shared objects without .set() / store methods — store
  • Import server-only code into client bundles — Ecosystem
  • Fight templates with manual innerHTMLhtml
  • Mount more than one Router or animatedRouter (shared patternsAtom) — Router
  • Nest routers for child screens — use paramsAtom / qsAtom conditionals — Router

Anti-patterns by area

Area
Common footgun
Read
State atom() in template / memo / effect atom, memo, effect
Components Capture propsFn() fields in outer scope Props, Component model
Actions Ignore .loading / .error; fire fetch every render asyncAction, Error handling
Router Second router for nested UI; forget next() on leave guards Router, Lock navigation
Lists Unkeyed map of large arrays Lists & repeat, Performance
Lifecycle Subscribe without cleanup onMount, onError