---
title: Async
description: This doc describes about the behavior with async.
nav: 8.99
keywords: async
published: 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.

```js
const countAtom = atom(1)
const asyncAtom = atom(async (get) => get(countAtom) * 2)
```

Jotai is inherently leveraging `Suspense` to handle asynchronous flows.

```jsx
const 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.

```js
const anotherAtom = atom(async (get) => (await get(asyncAtom)) / 2)
```

This also applies to an atom with write function.

```js
const 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.

```js
const 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.

```js
const 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 accommodate for that you need to type your atom explicitly and add `Promise<number>` as accepted value.

```ts
const 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).

```js
const 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 suspending

To 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.

```jsx
const 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.
