jotai-family

Parameterized atom collections for Jotai, with atomFamily and atomTree utilities.

Library
npm
v1.1.0
37stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
37/100Needs Attention
Development Activity52
Maintenance12
Community20
Maturity44
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
71/100Good
Architecture72
Code Quality76
Innovation62
Learning Curve74

jotai-family is a small utility package from the jotaijs organization that adds parameterized atom collections on top of Jotai’s atomic state model. Its atomFamily function creates a per-parameter cache of atoms — similar to Recoil’s atomFamily/selectorFamily — so a component can derive a distinct atom for each id, key, or other parameter without manually managing a map of atoms itself.

Beyond the basic family pattern, the package includes explicit memory-management controls (remove, setShouldRemove) to avoid unbounded cache growth when a family is keyed by an unbounded parameter space, plus an atomTree utility for hierarchical atom structures. Maintained by Jotai’s own author (Daishi Kato) alongside the jotaijs ecosystem, it is a focused, dependency-light addition for apps that need per-item or per-key derived state.

What You Get

  • atomFamily(initializeAtom, areEqual?) — a factory that returns a function mapping each distinct parameter to its own cached atom
  • Explicit cache controls: remove(param) to evict a single entry and setShouldRemove(fn) to register automatic eviction logic based on creation time or parameter
  • An unstable_listen hook that fires on atom creation/removal for advanced integration or debugging needs
  • Full TypeScript generics so the parameter and atom types are inferred from the initializeAtom function
  • An atomTree utility for building hierarchical/nested atom structures
  • A tiny, dependency-free implementation (backed by a Map) that adds negligible bundle weight

Common Use Cases

  • Deriving a distinct atom per list item, row id, or entity key without hand-rolling a Map of atoms
  • Reproducing Recoil’s atomFamily/selectorFamily pattern in a Jotai-based codebase, including deep-equality-based parameter matching
  • Managing memory in long-running apps with an unbounded parameter space by registering a shouldRemove eviction policy
  • Building nested or tree-shaped derived state with atomTree where child atoms depend on a parent key

Under The Hood

Architecture - The package is intentionally minimal: src/atomFamily.ts implements the family pattern as a closure over a Map<Param, [Atom, CreatedAt]>, exposing getParams, remove, setShouldRemove, and an unstable_listen event hook for creation/removal notifications; src/atomTree.ts implements a related tree-shaped variant; src/index.ts re-exports both. There is no internal dependency on Jotai’s store internals — it only needs the Atom type and the initializeAtom factory passed in by the caller, keeping it decoupled from Jotai’s core implementation.

Tech Stack - Pure TypeScript with a single peer dependency on jotai (used only for its Atom type import from jotai/vanilla), built to dual ESM/CJS output via Vite, and tested with Vitest. No other runtime dependencies are pulled in.

Code Quality - At 235 total lines across atomFamily.ts and atomTree.ts, the implementation is compact enough to audit in full; both files have a corresponding .test.ts in tests/, giving direct coverage of the creation, caching, removal, and listener-notification paths. Naming is consistent with Jotai’s own conventions and the optional custom-equality path is handled explicitly rather than silently defaulting.

API Design - The API surface is a single factory function returning a callable object with attached methods (remove, setShouldRemove, getParams), which mirrors how Jotai’s own atom() works and keeps the mental model familiar to existing Jotai users. TypeScript generics infer parameter and atom types automatically in the common case, and the README documents the memory-leak caveat directly with the two mitigation APIs, which is important since a naive family cache would otherwise grow unbounded.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search