Skip to content

What it is

Jotai is a primitive and flexible state management library for React. It provides atoms as units of state, allowing fine-grained control over state updates without the boilerplate of larger libraries like Redux.

Jotai uses atoms to define pieces of state. Components subscribe to atoms using the `useAtom` hook, automatically re-rendering when the atom’s value changes. Derived atoms allow computed state and asynchronous operations.

Installation

npm install jotai

Getting started

The smallest useful thing you can do with it, and what each part means.

Creating and using an atom
import { atom, useAtom } from 'jotai';

const countAtom = atom(0);

function Counter() {
  const [count, setCount] = useAtom(countAtom);
  return (
    <div>
      <button onClick={() => setCount(c => c - 1)}>-</button>
      <span>{count}</span>
      <button onClick={() => setCount(c => c + 1)}>+</button>
    </div>
  );
}
Defines an atom `countAtom` with an initial value of 0 and uses `useAtom` to read and update the state in a component.

Advanced usage

Where the library earns its place over a simpler alternative.

Derived atom
import { atom, useAtom } from 'jotai';

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

function DoubleCounter() {
  const [doubleCount] = useAtom(doubleCountAtom);
  return <div>Double Count: {doubleCount}</div>;
}
Creates a derived atom `doubleCountAtom` that computes its value from another atom.
Async atom
import { atom, useAtom } from 'jotai';

const asyncDataAtom = atom(async () => {
  const res = await fetch('https://api.example.com/data');
  return res.json();
});

function AsyncComponent() {
  const [data] = useAtom(asyncDataAtom);
  return <pre>{JSON.stringify(data, null, 2)}</pre>;
}
Demonstrates an asynchronous atom that fetches data from an API and makes it available to components.
Updating multiple atoms
import { atom, useAtom } from 'jotai';

const firstNameAtom = atom('John');
const lastNameAtom = atom('Doe');
const fullNameAtom = atom(
  get => `${get(firstNameAtom)} ${get(lastNameAtom)}`,
  (get, set, newFullName) => {
    const [first, last] = newFullName.split(' ');
    set(firstNameAtom, first);
    set(lastNameAtom, last);
  }
);
Shows a writable derived atom `fullNameAtom` that updates multiple underlying atoms when set.

Errors and fixes

The failures you are most likely to hit, and what actually resolves them.

Component not re-rendering
Ensure the component is using the `useAtom` hook and subscribing to the correct atom.
Derived atom not updating
Check that the derived atom properly reads from its dependencies using `get`.
Async atom throws error
Handle errors inside the async function or use `atomWithQuery` from Jotai utilities for safer async state.

Best practices

  • Keep atoms small and focused for better performance and reusability.
  • Use derived atoms for computed state instead of duplicating logic in components.
  • Handle asynchronous operations with async atoms or separate utility functions.
  • Avoid unnecessary re-renders by subscribing components only to the atoms they need.
  • Use `atomWithStorage` for persisting state in localStorage or sessionStorage.

Background

Why it exists, and what it was reacting to.

Jotai was created by Daishi Kato to offer a minimalistic alternative for React state management. Its design emphasizes simplicity, direct usage of React hooks, and a focus on atomic state, where each atom represents an independent piece of state.