Derived & Async Atoms

Compose atomic state dynamically and trigger native React Suspense with promises.

State Management7 min readConcept 20 of 22

Composition & Promises

A Derived Atom is created by passing a read function (get) => ... to atom(). By calling get(anotherAtom) inside this function, Jotai establishes a dynamic, runtime dependency graph.

An Async Atom is simply a derived atom whose read function returns a Promise (async (get) => ...).

No More useEffect

In standard React, coordinating dependent state variables or firing network requests when an ID changes often results in spaghetti useEffect chains.

Jotai handles this reactivity graph for you. When a base atom updates, any derived atoms automatically re-evaluate. If that evaluation is a fetch request, it happens seamlessly.

Native React Suspense

When a React component calls useAtomValue() on a pending Async Atom, Jotai automatically throws the Promise to React.

This triggers the nearest <Suspense> boundary natively, allowing you to build loading states without manually tracking isLoading or isError flags in your global store.

Interactive Lab: Async Suspense

Use the controls to change the User ID. The async atom will automatically refetch, trigger React Suspense, and animate the UI!

ID: 1
// 1. Base Atom const userIdAtom = atom(1); // 2. Async Derived Atom (Returns a Promise) const userDataAtom = atom(async (get) => { const id = get(userIdAtom); const res = await fetch(`/users/${id}`); return res.json(); }); // 3. React natively Suspends while pending! function Profile() { const data = useAtomValue(userDataAtom); return <div>{data.name}</div>; }
Suspending...

Click Next User. Jotai updates the base atom, re-evaluates the derived async atom, and throws the pending Promise to React's native Suspense boundary!

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1What happens by default when a React component reads an Async Atom that is still resolving its Promise?

Remember this

  • Derived atoms are created by passing a function (get) => ... to atom().
  • Jotai tracks dependencies dynamically at runtime on every evaluation.
  • Async Atoms are just derived atoms that return a Promise.
  • Jotai natively suspends components while Async Atoms are pending.

Done with this concept?

Mark it complete to track your progress. No login needed.