ScriptsApr 14, 2026·3 min read

Jotai — Primitive and Flexible State Management for React

Jotai is an atomic state library for React. You compose atoms like React useState, and Jotai handles subscription, derivation, and async loading — all without the boilerplate of Redux or the global store of Zustand.

TL;DR
Jotai provides atomic state for React with derivation, async support, and zero Redux-style boilerplate.
§01

What it is

Jotai is an atomic state management library for React. Instead of a single global store, you define independent atoms that hold pieces of state. Components subscribe to only the atoms they use, so re-renders are minimal. Derived atoms compute values from other atoms, and async atoms handle data fetching -- all with an API as simple as useState.

Jotai targets React developers who find Redux too heavy and Context too limited. It suits applications where fine-grained reactivity and composable state pieces matter more than a centralized store.

§02

How it saves time or tokens

Redux requires slices, reducers, actions, selectors, and middleware for even simple state. Zustand simplifies this but still uses a single store. Jotai eliminates all boilerplate: define an atom, use it in a component with useAtom. Derived state is a function, not a selector library. The mental model is useState that works across components.

§03

How to use

  1. Install Jotai: npm install jotai.
  2. Define atoms: const countAtom = atom(0) and derived atoms: const doubledAtom = atom((get) => get(countAtom) * 2).
  3. Use in components: const [count, setCount] = useAtom(countAtom).
§04

Example

import { atom, useAtom } from 'jotai';

const countAtom = atom(0);
const doubledAtom = atom((get) => get(countAtom) * 2);

function Counter() {
  const [count, setCount] = useAtom(countAtom);
  const [doubled] = useAtom(doubledAtom);
  return (
    <div>
      <button onClick={() => setCount(c => c + 1)}>
        Count: {count}, Doubled: {doubled}
      </button>
    </div>
  );
}
§05

Related on TokRepo

§06

Common pitfalls

  • Creating atoms inside component render functions. Atoms should be defined at module scope or memoized. Creating them during render causes infinite re-renders.
  • Not using Provider when you need isolated state trees (e.g., in tests or micro-frontends). Without a Provider, all components share the default store.
  • Overusing derived atoms for simple transformations that could be done inline. Atoms add subscription overhead, so only extract derived atoms when multiple components need the same computation.

Frequently Asked Questions

How does Jotai compare to Zustand?+

Zustand uses a single store with selectors for fine-grained subscriptions. Jotai uses independent atoms with no central store. Zustand is better for teams that prefer a single source of truth with clear boundaries. Jotai is better when state is naturally decentralized and composed from many small pieces.

Does Jotai support async state?+

Yes. Define an async atom with `atom(async (get) => { ... })` and Jotai handles loading states through React Suspense. When the async atom resolves, subscribed components re-render with the fetched data.

Can Jotai persist state to localStorage?+

Yes. Use `atomWithStorage` from the `jotai/utils` package. It syncs atom values to localStorage, sessionStorage, or a custom storage backend automatically. State persists across page reloads and browser tabs.

Does Jotai work with React Server Components?+

Jotai atoms use React hooks and run in Client Components. For Server Components, pass server-fetched data as props into Client Components that use Jotai for interactive state management.

How large is Jotai?+

Jotai's core is under 3KB gzipped. It has no dependencies beyond React. The small size makes it suitable for performance-sensitive applications where bundle size matters.

Citations (3)

Discussion

Sign in to join the discussion.
No comments yet. Be the first to share your thoughts.

Related Assets