👻 Primitive and flexible state management for React
Jotai is an atomic state management library for React that treats state as independent atoms rather than a single store. Each atom represents a piece of state that components can subscribe to, and Jotai automatically tracks dependencies to optimize re-renders. At just 2kb, it provides a minimal API surface while solving the performance problems inherent in React Context.
The library was created as a lighter, more flexible alternative to Recoil, borrowing its atomic model but with a simpler implementation. Atoms in Jotai are defined outside components and can be primitive values, objects, or derived computations from other atoms. Unlike Redux or Zustand which use a top-down store approach, Jotai's bottom-up design means you define only the atoms you need without boilerplate.
Jotai has gained significant traction with over 2.5 million weekly downloads, adopted by teams building everything from simple dashboards to complex enterprise applications. It works seamlessly with Next.js, Remix, and React Native, offering built-in support for async operations, Suspense integration, and server-side rendering. The library is TypeScript-first, providing excellent type inference without manual type annotations.
The core philosophy centers on primitivity and composability. You can start with atoms as simple useState replacements and gradually compose them into sophisticated state graphs. Optional utilities enable localStorage persistence, DevTools integration, and framework-specific optimizations, but the core remains intentionally minimal.
import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai';
import { atomWithStorage } from 'jotai/utils';
// Primitive atom
const countAtom = atom(0);
// Atom with localStorage persistence
const themeAtom = atomWithStorage('theme', 'light');
// Async atom for data fetching
const userAtom = atom(async (get) => {
const userId = get(userIdAtom);
const response = await fetch(`/api/users/${userId}`);
return response.json();
});
// Derived atom (read-only)
const doubleCountAtom = atom((get) => get(countAtom) * 2);
// Derived atom with write function
const incrementAtom = atom(
(get) => get(countAtom),
(get, set, amount: number) => {
set(countAtom, get(countAtom) + amount);
}
);
function Counter() {
// Read and write
const [count, setCount] = useAtom(countAtom);
// Read-only (optimized)
const doubleCount = useAtomValue(doubleCountAtom);
// Write-only (component won't re-render on changes)
const increment = useSetAtom(incrementAtom);
return (
<div>
<p>Count: {count}</p>
<p>Double: {doubleCount}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
<button onClick={() => increment(5)}>+5</button>
</div>
);
}
function ThemeToggle() {
const [theme, setTheme] = useAtom(themeAtom);
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Current: {theme}
</button>
);
}Global UI state coordination: Managing modal visibility, theme preferences, sidebar state, and notification queues across deeply nested component trees without prop drilling or Context performance penalties.
Async data fetching and caching: Creating atoms that fetch data from APIs, automatically handling loading states, errors, and Suspense boundaries. Derived atoms can depend on multiple async sources, with Jotai handling the coordination.
Form state management: Building complex forms where field validation depends on other fields, with automatic re-computation when dependencies change. Atoms can represent individual fields or entire form sections with independent update cycles.
Real-time collaborative features: Managing WebSocket connections and optimistically updating local state while syncing with server state. Atoms can hold connection status, user presence data, and document changes with fine-grained subscriptions.
Feature flags and A/B testing: Storing experiment configurations in atoms that components subscribe to, allowing dynamic feature toggles without full page reloads. Derived atoms can compute variant assignments based on user properties.
A tiny (265 bytes) state manager for React/Preact/Vue/Svelte with many atomic tree-shakable stores
Recoil - A state management library for React
Predictable state container for JavaScript apps
🧙 Valtio makes proxy-state simple for React and Vanilla
🐻 Bear necessities for state management in React
npm install jotaipnpm add jotaibun add jotai