Guide · Open source
How to use Jotai: atoms, derived state and async in React
Updated · written with AI from the project's own documentation and checked against our catalogue data
Jotai is a state management library for React apps. You store pieces of state as small units called atoms, and components read and update them much like React's useState. This guide shows you how to install it, create primitive and derived atoms, handle async data, and decide whether it fits your project.
Quick start
- 1Install Jotai. Run npm i jotai in your project. You need Node.js and npm installed.
- 2Create a primitive atom. Import atom from jotai and call it with an initial value, such as atom(0).
- 3Read and write with useAtom. Call useAtom(yourAtom) in a component to get a value and a setter, the same way you would use React.useState.
- 4Add a derived atom. Create a read-only atom with a read function that calls get on other atoms.
- 5Add an async atom or action. Make the read function async for fetched data, or make a write function async to update state after a request. Use React Suspense for async reads.
- 6Check the docs. Read the Jotai documentation at jotai.org/docs for more patterns and utilities.
Install Jotai with npm
Jotai is installed from npm. The project's prerequisites are Node.js and npm. Run the install command in your project folder.
- Prerequisites: Node.js and npm
- Jotai's homepage is jotai.org, and the documentation is at jotai.org/docs
npm i jotaiCreate a primitive atom
An atom represents a piece of state. You specify an initial value, which can be a primitive such as a string or number, an object, or an array. You can create as many primitive atoms as you want.
import { atom } from 'jotai'
const countAtom = atom(0)
const countryAtom = atom('Japan')
const citiesAtom = atom(['Tokyo', 'Kyoto', 'Osaka'])
const mangaAtom = atom({ 'Dragon Ball': 1984, 'One Piece': 1997, Naruto: 1999 })Read and update atoms in components with useAtom
An atom can be used in a component like React.useState. useAtom returns the current value and a setter, so a button can update the count.
import { useAtom } from 'jotai'
function Counter() {
const [count, setCount] = useAtom(countAtom)
return (
<h1>
{count}
<button onClick={() => setCount((c) => c + 1)}>one up</button>
...Create derived atoms from other atoms
A new read-only atom can be created from existing atoms by passing a read function as the first argument. The get function fetches the current value of any atom, so derived values stay in sync automatically.
You can also combine several atoms into one derived atom, either by listing them or by mapping over an array of atoms.
- Read-only derived atom: atom((get) => get(countAtom) * 2)
- Combined atom: atom((get) => get(count1) + get(count2) + get(count3))
const doubledCountAtom = atom((get) => get(countAtom) * 2)
function DoubleCounter() {
const [doubledCount] = useAtom(doubledCountAtom)
return <h2>{doubledCount}</h2>
}Fetch async data with async atoms
The read function can be async. The README notes this pattern needs React Suspense. The component re-renders after the async function concludes, and again when the atom it depends on changes.
const urlAtom = atom('https://json.host.com')
const fetchUrlAtom = atom(async (get) => {
const response = await fetch(get(urlAtom))
return await response.json()
})
function Status() {
const [json] = useAtom(fetchUrlAtom)
...Write to state with writable and write-only atoms
A writable derived atom takes a write function as its second argument. get reads the current value of an atom and set updates it. If you do not define a read function, the atom is write-only. Write functions can also be async: make them async and call set when your data is ready.
- Writable derived atom: atom(read, write)
- Write-only atom: atom(null, write)
- Async action: an async write function that calls set after a fetch
const multiplyCountAtom = atom(null, (get, set, by) =>
set(countAtom, get(countAtom) * by),
)
function Controls() {
const [, multiply] = useAtom(multiplyCountAtom)
return <button onClick={() => multiply(3)}>triple</button>
}What people use it for
- Sharing a counter or form value between components without a large central store
- Computing a total or doubled value from several pieces of state
- Fetching JSON from a URL and storing the result as state
- Splitting app state into small atoms for a larger TypeScript application
Frequently asked questions
How do I install Jotai?
Run npm i jotai in your project folder. The README lists Node.js and npm as the prerequisites. Then import atom and useAtom from 'jotai' in your code.
Is Jotai free to use?
Jotai is released under the MIT licence, according to its repository. The MIT licence allows use, modification and distribution, with the licence text retained.
Can I use Jotai without React?
The README only shows React usage, so it does not document use in non-React projects. If you work outside React, check the official docs at jotai.org before deciding.
What is an atom in Jotai?
An atom is a small unit of state. You create it with an initial value, and components read and update it much like React's useState.
How is Jotai different from Recoil?
The README says Jotai has no string keys, which it contrasts with Recoil. It also describes a minimal core API of about 2kb. Recoil is one of the comparable projects listed for Jotai.
Why does my async atom need Suspense?
The README marks derived async atoms as needing React Suspense. Wrap the component that reads the async atom in a Suspense boundary so React can show a fallback while the data loads.
New agent skills, repos and AI tools — every week
The best new skills and open-source projects, the fastest-growing repos, and one free prompt. Five minutes to read. Unsubscribe anytime.
Our verdict
Jotai suits React developers who want simple shared state, typed state in TypeScript, or derived and async values without a large single store. Teams that want one central store with strict conventions, non-React projects, and people new to programming may prefer another option such as Redux Toolkit or Zustand.
Install options & downloads