Skip to main content


👻 Primitive and flexible state management for React
Go to Latest
---title: Asyncdescription: This doc describes about the behavior with async.nav: 7.99keywords: asyncpublished: false---
Using async atoms, you gain access to real-world data while still managing them directly from your atoms and with incredible ease.
We can separate them in two main categories:
- Async read atoms: async request is started instantly as soon as you try to get its value. You could relate to them as "smart getters".- Async write atoms: async request is started at a specific moment. You could relate to them as "actions".## Async read atom
The `read` function of an atom can return a promise.
```jsconst countAtom = atom(1)const asyncAtom = atom(async (get) => get(countAtom) * 2)```
Jotai is inherently leveraging `Suspense` to handle asynchronous flows.
```jsxconst ComponentUsingAsyncAtoms = () => { const [num] = useAtom(asyncAtom) // here `num` is always `number` even though asyncAtom returns a Promise}const App = () => { return ( <Suspense fallback={/* What to show while suspended */}> <ComponentUsingAsyncAtoms /> </Suspense> )}```
Alternatively, you could avoid the inherent suspending that Jotai does for you, by wrapping your atoms with the [`loadable` API](../utilities/async.mdx).
If another atom uses an async atom, it will return a promise. So, we need to make the atom also async.
```jsconst anotherAtom = atom(async (get) => (await get(asyncAtom)) / 2)```
This also applies to an atom with write function.
```jsconst asyncAtom = atom(async (get) => ...)const writeAtom = atom(null, async (get, set, payload) => { await get(asyncAtom) // ...})```
## Async write atom
Async write atoms are another kind of async atom. When the `write` function of atom returns a promise.
```jsconst countAtom = atom(1)const asyncIncrementAtom = atom(null, async (get, set) => { // await something set(countAtom, get(countAtom) + 1)})
const Component = () => { const [, increment] = useAtom(asyncIncrementAtom) const handleClick = () => { increment() } // ...}```
## Async sometimes
An interesting pattern that can be achieved with Jotai is switching from async to sync to trigger suspending when wanted.
```jsconst request = async () => fetch('https://...').then((res) => res.json())const baseAtom = atom(0)const Component = () => { const [value, setValue] = useAtom(baseAtom) const handleClick = () => { setValue(request()) // Will suspend until request resolves } // ...}```
### Usage in TypeScript
In TypeScript `atom(0)` is inferred as `PrimitiveAtom<number>`. It cannot accept `Promise<number>` as a value so preceding code would not typecheck. To accomodate for that you need to type your atom explicitly and add `Promise<number>` as accepted value.
```tsconst baseAtom = atom<number | Promise<number>>(0) // Will accept sync and async values```
## Async forever
Sometimes you may want to suspend until an unpredetermined moment (or never).
```jsconst baseAtom = atom(new Promise(() => {})) // Will be suspend until set otherwise```
## Suspense
Async support is first class in Jotai. It fully leverages React Suspense at its core.
> Technically, Suspense usage other than React.lazy is still unsupported / undocumented in React 17. If this is blocking, so you can still use the [`loadable` API](../utilities/async.mdx) to avoid suspendingTo use async atoms, you need to wrap your component tree with `<Suspense>`.
> If you have a `<Provider>`, place **at least one** `<Suspense>` inside said `<Provider>`; otherwise, it may cause an endless loop while rendering the components.```jsxconst App = () => ( <Provider> <Suspense fallback="Loading..."> <Layout /> </Suspense> </Provider>)```
Having more `<Suspense>`s in the component tree is also possible and must be considered to profit from Jotai inherent handling at best.