Documentation
Docs
Introduction
Getting Started
Tutorial: build an app
Core Concepts
Routing
Server-Side Rendering
Mimir, state management
Pages & Layouts
API Routes
Styling & Theming
Building & Deploying
API Reference
Guides
Recipes
FAQ (use cases)
Selectors
A selector is read-only state derived from other atoms (or selectors). You declare how to compute a value; Mimir tracks which atoms it read and recomputes (and re-notifies) only when one of those changes.
Defining a selector
key, a unique string (its own namespace from atoms is good practice).get(api), a pure function. It receives an object with agetfunction; callget(x)to read another
atom or selector. Every atom/selector you read this way becomes a tracked dependency.
Selectors are read-only: you cannot set a selector or pass one to useSetAtom. To "change" derived
state, change the atoms it derives from.
Automatic dependency tracking
You do not declare dependencies; Mimir records them as your get runs. When you read get(cartAtom) inside
the selector, cartAtom is added to the selector's dependency set. Later, when cartAtom changes, Mimir
recomputes the selector and notifies its subscribers, but not when an unrelated atom changes.
This means a component reading cartTotal re-renders exactly when the cart changes, and a component reading
the theme re-renders exactly when the theme changes, with no manual wiring.
Selectors can depend on selectors
A selector may read another selector. Mimir propagates the transitive leaf-atom dependencies, so a change to a deep underlying atom still notifies the top selector:
Cycle protection
If a selector reads itself, directly or through a chain, it would recurse forever and crash the process. Mimir detects re-entry and throws a clean error instead:
Mimir: circular selector dependency at 'cart:taxed'If you see this, you have an accidental loop (selector A reads B which reads A). Break the cycle.
Reading selectors
- In components:
useAtomValue(mySelector)(subscribes; re-renders on dependency change). - Outside React:
mimir.get(mySelector)(computes the current value).
useAtom's tuple form is not for selectors (there is no setter); use useAtomValue.
Selectors are computed, not stored
A selector's value is computed on read from the current atom values; it is not a separate stored slot you
can mutate. This keeps derived state always-consistent: there is no way for cartTotal to drift out of sync
with cartAtom, because it is recomputed from it.
When to use a selector vs computing in the component
- Use a selector when the derivation is shared by several components, or feeds another selector, or you
want the dependency-scoped re-render behaviour (only recompute when inputs change).
- Compute inline in a component when the derivation is local and cheap,
const total = items.reduce(...)
in the component reading items is perfectly fine for a one-off.
Selectors shine for cross-cutting derived values: a cart total used in the header and the checkout, a "filtered, sorted list" several views render, a "is the form valid" flag many fields depend on.
Next: reacting to changes outside React, Subscriptions.