@stainless-code/persist
Version:
Hydration-aware persistence for any reactive store — zero-dep persistSource core; codecs, backends, cross-tab transport, source + framework hydration adapters ship as opt-in recipes
65 lines (46 loc) • 2.31 kB
Markdown
---
name: persist-jotai
description: Persist a jotai WritableAtom via createStore with @stainless-code/persist (persistAtom). Use when wiring jotai atoms to localStorage/sessionStorage/IndexedDB, or when default replace-merge for primitive atoms matters.
license: MIT
metadata:
type: composition
library: "@stainless-code/persist"
library_version: "0.4.1"
framework: "jotai"
sources:
- stainless-code/persist:src/adapters/sources/jotai.ts
- stainless-code/persist:docs/architecture.md
---
# Persisting jotai
`@stainless-code/persist/sources/jotai` persists a **WritableAtom** through a jotai **Store** (`createStore()` → `{ get, set, sub }`).
## When to use this skill
- You own a writable jotai atom and a store, and want reload survival.
- Atom values may be primitives — default merge must **replace**, not shallow-spread.
Zustand / TanStack Store → those `persist-*` skills. Hand-rolled → `persistSource`.
## Install
```bash
bun add @stainless-code/persist jotai
```
`jotai` is an optional peer of `/sources/jotai`.
## Minimal wiring
```ts
import { atom, createStore } from "jotai";
import { createJSONStorage } from "@stainless-code/persist";
import { persistAtom } from "@stainless-code/persist/sources/jotai";
const themeAtom = atom<"light" | "dark">("light");
const store = createStore();
const persist = persistAtom(store, themeAtom, {
name: "app:theme:v1",
storage: createJSONStorage(() => localStorage),
});
```
Needs **both** `store` and `atom`. Provider-only / atom-without-store is not enough.
## Replace-merge default
Default `merge` is `(persisted) => persisted`. Shallow-spreading a primitive corrupts it (`{...number}` → `{}`). Pass your own `merge` for object atoms that need spread-merge. Override uses `??`, so `merge: undefined` still replace-merges.
## Common mistakes
- **Omitting `createStore`.** `persistAtom(store, atom, opts)` — store first.
- **Readonly / computed atoms.** Typed as `WritableAtom` only — **no** runtime throw (unlike TanStack `persistAtom`).
- **Assuming object shallow-merge.** Primitives need replace (the default).
## API surface
- `persistAtom(store, atom, options) → PersistApi`
- Options / `PersistApi`: see skill `persist`. Replace-merge also used by TanStack `persistAtom` (`persist-tanstack-store`).