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 /
memofor computed values — memo - Return cleanup from
onMountwhen you subscribe — onMount - Use
asyncActionfor server data with loading UI — asyncAction - Colocate routes in one
Router([...], NotFound)oranimatedRouter; nest UI withparamsAtom()/qsAtom()— Router - Navigate with
useUtils().navigateTo— atom.setalso navigates (optional replace) — navigate - Guard leave with
onNavigationRequest— callnext()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
effectto copy atom → atom when derivation /memoworks — 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
innerHTML— html - Mount more than one
RouteroranimatedRouter(sharedpatternsAtom) — Router - Nest routers for child screens — use
paramsAtom/qsAtomconditionals — 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 |