Jotai and Atomic State
Jotai implements the atomic state model - state is broken into small, independent units called atoms.
Basic atoms
ts
import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai';
// define atoms
const countAtom = atom(0);
const nameAtom = atom('Alice');
const darkModeAtom = atom(false);Using atoms
tsx
function Counter() {
const [count, setCount] = useAtom(countAtom);
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}
function Display() {
const count = useAtomValue(countAtom); // read only
return <span>{count}</span>;
}
function ResetButton() {
const setCount = useSetAtom(countAtom); // write only - no re-render on change
return <button onClick={() => setCount(0)}>Reset</button>;
}Derived atoms
ts
const cartAtom = atom([{ id: 1, price: 10 }, { id: 2, price: 25 }]);
// derived - recalculates when cartAtom changes
const totalAtom = atom((get) => {
const cart = get(cartAtom);
return cart.reduce((sum, item) => sum + item.price, 0);
});Async atoms
ts
const userAtom = atom(async (get) => {
const id = get(userIdAtom);
const res = await fetch(`/api/users/${id}`);
return res.json();
});
// use with Suspense
function UserProfile() {
const user = useAtomValue(userAtom); // suspends until resolved
return <div>{user.name}</div>;
}Jotai vs Zustand vs Redux
| Redux | Zustand | Jotai | |
|---|---|---|---|
| Model | Single store | Single store | Atoms |
| Bundle size | ~11kb | ~1kb | ~3kb |
| Re-renders | Selector-based | Selector-based | Atom subscription |
| Code splitting | Manual | Manual | Automatic |
| Best for | Large teams | General use | Fine-grained reactivity |
Jotai shines when you have many small, independent pieces of state that components subscribe to individually - each component only re-renders when its exact atoms change.
updated
did you know it?