Async
Async support is first class in jotai. It fully leverages React Suppense.
Technically, Suspense usage other than React.lazy is still unsupported / undocumented in React 17. If this is blocking, check out guides/no-suspense.
Suspense
To use async atoms, you need to wrap your component tree with <Suspense>
.
If you have <Provider>
at least one <Suspense>
is placed inside the <Provider>
.
const App = () => (
<Provider>
<Suspense fallback="Loading...">
<Layout />
</Suspense>
</Provider>
)
Having more <Suspense>
s in the component tree is possible.
Async read atom
The read
function of an atom can return a promise.
It will suspend and re-render when the promise is fulfilled.
Most importantly, useAtom only returns a resolved value.
const countAtom = atom(1)
const asyncCountAtom = atom(async (get) => get(countAtom) * 2)
// even though the read function returns a promise,
const Component = () => {
const [num] = useAtom(asyncCountAtom)
// `num` is guaranteed to be a number.
}
An atom becomes async not only if the atom read function is async, but also one or more of its dependencies are async.
const anotherAtom = atom((get) => get(asyncCountAtom) / 2)
// even though this atom doesn't return a promise,
// it is a read async atom because `asyncCountAtom` is async.
Async write atom
There are another kind of async atoms, called async write atom.
When write
function of atom returns a promise, it may suspend.
This happens only if the atom is used directly with useAtom,
regardless of its value. (The atom value can be just null
.)
const countAtom = atom(1)
const asyncIncrementAtom = atom(null, async (get, set) => {
// await something
set(countAtom, get(countAtom) + 1)
})
const Component = () => {
const [, increment] = useAtom(asyncIncrementAtom)
// it will suspend while `increment` is pending.
}
There's no way to know as of now if an atom suspends because of
read
orwrite
.