/web-state-jotai
Atomic state management with auto-dependency tracking
$ npx -y skills add agents-inc/skills --skill web-state-jotai --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/web-state-jotai
Context preview
The summary Claude sees to decide when to auto-load this skill.
Atomic state management with auto-dependency tracking
SKILL.md
web-state-jotai.SKILL.mdname: web-state-jotai
description: Atomic state management with auto-dependency tracking
Jotai Atomic State Management
> **Quick Guide:** Jotai provides atomic, bottom-up state management with automatic dependency tracking. Define atoms at module level (never inside components). Use primitive atoms for values, derived atoms for computed state, write-only atoms for actions, and async atoms with Suspense for loading. Components only re-render when their specific atoms change. The `atomFamily` utility is deprecated -- use the `jotai-family` package for new code.
---
<critical_requirements>
CRITICAL: Before Using Jotai
**(You MUST define atoms OUTSIDE components -- creating atoms inside render causes broken state)**
**(You MUST wrap async atom consumers in Suspense boundaries -- async atoms trigger Suspense by default)**
**(You MUST use write atoms (action atoms) to encapsulate multi-atom updates and post-async state changes)**
**(You MUST use `jotai-family` package instead of deprecated `atomFamily` from `jotai/utils` for new code)**
</critical_requirements>
---
**Auto-detection:** Jotai, jotai, atom, useAtom, useAtomValue, useSetAtom, atomWithStorage, atomFamily, splitAtom, selectAtom, derived atom, loadable, unwrap, createStore, Provider store
**When to use:**
- Fine-grained reactivity without manual memoization
- Bottom-up state composition with automatic dependency tracking
- Async state with React Suspense integration
- Computed/derived state that auto-updates when dependencies change
- Avoiding prop drilling for shared UI state
**Key patterns covered:**
- Primitive, derived, write-only, and read-write atoms
- Async atoms with Suspense and loadable/unwrap utilities
- atomWithStorage for persistence
- splitAtom for array item isolation
- Store and Provider patterns for isolation and testing
**When NOT to use:**
- Server/API data (use your data fetching solution)
- Simple local component state (use useState)
- State that should be in URL (use searchParams)
---
<philosophy>
Philosophy
Jotai takes an **atomic, bottom-up approach** to state management. The core principle: **"Anything that can be derived from the application state should be derived automatically."**
Consider atoms like cells in a spreadsheet:
- Each atom is an independent cell holding a value
- Derived atoms are formulas that reference other cells
- When a cell changes, only formulas depending on it recalculate
- This provides the minimum necessary work automatically
**Key characteristics:**
- **Bottom-up state design**: Build state from small, composable atoms
- **Automatic dependency tracking**: Atoms automatically update when dependencies change
- **Fine-grained reactivity**: Components only re-render when their specific atoms change
- **First-class async support**: Async operations integrate seamlessly with React Suspense
**Mental Model:** Instead of one large store, you have many small atoms that can be combined. This creates natural code splitting and enables precise re-render optimization without manual memoization.
</philosophy>
---
<patterns>
Core Patterns
Pattern 1: Primitive Atoms
The simplest atom type -- holds a single value with automatic type inference. Always define at module level.
import { atom } from "jotai";
const INITIAL_COUNT = 0;
const countAtom = atom(INITIAL_COUNT);
const userAtom = atom<User | null>(null);
export { countAtom, userAtom };**Why good:** Module-level definition persists state, type inference works automatically, explicit typing only for unions/nullable
See [examples/core.md](examples/core.md) Pattern 1 for complete examples with type patterns.
---
Pattern 2: Derived (Read-Only) Atoms
Compute values from other atoms -- dependencies tracked automatically, cached until dependencies change.
const subtotalAtom = atom((get) => get(priceAtom) * get(quantityAtom));
const taxAtom = atom((get) => get(subtotalAtom) * get(taxRateAtom));
const totalAtom = atom((get) => get(subtotalAtom) + get(taxAtom));
**Why good:** Automatic dependency tracking, cached computation, chain of derivations is composable
See [examples/core.md](examples/core.md) Pattern 2 for derived atom chains and conditional derivations.
---
Pattern 3: Write-Only Atoms (Action Atoms)
Encapsulate side effects and multi-atom updates. First argument is `null` (no read value).
const resetAllAtom = atom(null, (get, set) => {
set(countAtom, 0);
set(itemsAtom, []);
set(selectedAtom, null);
});**Why good:** Actions are reusable, enables code splitting, multiple atoms updated atomically
See [examples/core.md](examples/core.md) Pattern 3 for action atoms with arguments.
---
Pattern 4: Read-Write Atoms
Atoms that can both read derived state and accept writes. Useful for lens-like property access on larger objects.
const nameAtom = atom(
(get) => get(userAtom).name,
(get, set, newName: string) => {
set(userAtom, { ...get(userAtom), name: newName });
},
);**Why good:** Granular read/write access to object properties, keeps parent intact
See [examples/core.md](examples/core.md) Pattern 4 for lens patterns and transformations.
---
Pattern 5: Async Atoms with Suspense
Async atoms trigger Suspense by default. Use `loadable()` for manual loading states or `unwrap()` for fallback values.
// Triggers Suspense -- wrap consumer in <Suspense>
const userAtom = atom(async (get) => {
const id = get(userIdAtom);
const response = await fetch(`/api/users/${id}`);
return response.json() as Promise<User>;
});
// Non-Suspense alternative
const loadableUserAtom = loadable(userAtom);
// Returns { state: 'loading' } | { state: 'hasData', data } | { state: 'hasError', error }**Why good:** First-class Suspense integration, loadable provides type-safe discriminated union
See [examples/async.md](examples/async.md) for Suspense setup, loadable/unwrap patterns
Read more
name: web-state-jotai description: Atomic state management with auto-dependency tracking
Jotai Atomic State Management
> **Quick Guide:** Jotai provides atomic, bottom-up state management with automatic dependency tracking. Define atoms at module level (never inside components). Use primitive atoms for values, derived atoms for computed state, write-only atoms for actions, and async atoms with Suspense for loading. Components only re-render when their specific atoms change. The `atomFamily` utility is deprecated -- use the `jotai-family` package for new code.
---
<critical_requirements>
CRITICAL: Before Using Jotai
**(You MUST define atoms OUTSIDE components -- creating atoms inside render causes broken state)**
**(You MUST wrap async atom consumers in Suspense boundaries -- async atoms trigger Suspense by default)**
**(You MUST use write atoms (action atoms) to encapsulate multi-atom updates and post-async state changes)**
**(You MUST use `jotai-family` package instead of deprecated `atomFamily` from `jotai/utils` for new code)**
</critical_requirements>
---
**Auto-detection:** Jotai, jotai, atom, useAtom, useAtomValue, useSetAtom, atomWithStorage, atomFamily, splitAtom, selectAtom, derived atom, loadable, unwrap, createStore, Provider store
**When to use:**
- Fine-grained reactivity without manual memoization
- Bottom-up state composition with automatic dependency tracking
- Async state with React Suspense integration
- Computed/derived state that auto-updates when dependencies change
- Avoiding prop drilling for shared UI state
**Key patterns covered:**
- Primitive, derived, write-only, and read-write atoms
- Async atoms with Suspense and loadable/unwrap utilities
- atomWithStorage for persistence
- splitAtom for array item isolation
- Store and Provider patterns for isolation and testing
**When NOT to use:**
- Server/API data (use your data fetching solution)
- Simple local component state (use useState)
- State that should be in URL (use searchParams)
---
<philosophy>
Philosophy
Jotai takes an **atomic, bottom-up approach** to state management. The core principle: **"Anything that can be derived from the application state should be derived automatically."**
Consider atoms like cells in a spreadsheet:
- Each atom is an independent cell holding a value
- Derived atoms are formulas that reference other cells
- When a cell changes, only formulas depending on it recalculate
- This provides the minimum necessary work automatically
**Key characteristics:**
- **Bottom-up state design**: Build state from small, composable atoms
- **Automatic dependency tracking**: Atoms automatically update when dependencies change
- **Fine-grained reactivity**: Components only re-render when their specific atoms change
- **First-class async support**: Async operations integrate seamlessly with React Suspense
**Mental Model:** Instead of one large store, you have many small atoms that can be combined. This creates natural code splitting and enables precise re-render optimization without manual memoization.
</philosophy>
---
<patterns>
Core Patterns
Pattern 1: Primitive Atoms
The simplest atom type -- holds a single value with automatic type inference. Always define at module level.
import { atom } from "jotai";
const INITIAL_COUNT = 0;
const countAtom = atom(INITIAL_COUNT);
const userAtom = atom<User | null>(null);
export { countAtom, userAtom };**Why good:** Module-level definition persists state, type inference works automatically, explicit typing only for unions/nullable
See [examples/core.md](examples/core.md) Pattern 1 for complete examples with type patterns.
---
Pattern 2: Derived (Read-Only) Atoms
Compute values from other atoms -- dependencies tracked automatically, cached until dependencies change.
const subtotalAtom = atom((get) => get(priceAtom) * get(quantityAtom)); const taxAtom = atom((get) => get(subtotalAtom) * get(taxRateAtom)); const totalAtom = atom((get) => get(subtotalAtom) + get(taxAtom));
**Why good:** Automatic dependency tracking, cached computation, chain of derivations is composable
See [examples/core.md](examples/core.md) Pattern 2 for derived atom chains and conditional derivations.
---
Pattern 3: Write-Only Atoms (Action Atoms)
Encapsulate side effects and multi-atom updates. First argument is `null` (no read value).
const resetAllAtom = atom(null, (get, set) => {
set(countAtom, 0);
set(itemsAtom, []);
set(selectedAtom, null);
});**Why good:** Actions are reusable, enables code splitting, multiple atoms updated atomically
See [examples/core.md](examples/core.md) Pattern 3 for action atoms with arguments.
---
Pattern 4: Read-Write Atoms
Atoms that can both read derived state and accept writes. Useful for lens-like property access on larger objects.
const nameAtom = atom(
(get) => get(userAtom).name,
(get, set, newName: string) => {
set(userAtom, { ...get(userAtom), name: newName });
},
);**Why good:** Granular read/write access to object properties, keeps parent intact
See [examples/core.md](examples/core.md) Pattern 4 for lens patterns and transformations.
---
Pattern 5: Async Atoms with Suspense
Async atoms trigger Suspense by default. Use `loadable()` for manual loading states or `unwrap()` for fallback values.
// Triggers Suspense -- wrap consumer in <Suspense>
const userAtom = atom(async (get) => {
const id = get(userIdAtom);
const response = await fetch(`/api/users/${id}`);
return response.json() as Promise<User>;
});
// Non-Suspense alternative
const loadableUserAtom = loadable(userAtom);
// Returns { state: 'loading' } | { state: 'hasData', data } | { state: 'hasError', error }**Why good:** First-class Suspense integration, loadable provides type-safe discriminated union
See [examples/async.md](examples/async.md) for Suspense setup, loadable/unwrap patterns
Showing the first part of this file.
The official skills marketplace for Agents Inc. 150+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?
Repo: agents-inc/skills
Other skills on agents-inc-skills.
- /ai-infrastructure-huggingface-inference
Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming, embeddings, image generation, audio transcription, translation, summarization, and Inference Endpoints
Open skill - /ai-infrastructure-litellm
LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking, virtual keys, and production deployment
Open skill - /ai-infrastructure-modal
Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client patterns
Open skill - /ai-infrastructure-ollama
Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output, model management, and OpenAI-compatible endpoint
Open skill - /ai-infrastructure-replicate
Replicate SDK patterns for TypeScript/Node.js -- client setup, predictions, streaming, webhooks, file handling, model versioning, deployments, and training
Open skill - /ai-infrastructure-together-ai
Together AI SDK patterns for TypeScript — client setup, chat completions, streaming, structured output, function calling, embeddings, image generation, fine-tuning, and OpenAI-compatible endpoints
Open skill

