# @postinumero/use-async

> Create a suspending hook from an async function, an async generator or a function that returns an async iterator.

Latest version **1.0.0** (published 2025-06-02) · ISC license · 0 weekly downloads

## Install

```sh
npm install @postinumero/use-async
pnpm add @postinumero/use-async
yarn add @postinumero/use-async
bun add @postinumero/use-async
```

## Health

**Score 35/100 (D)** — status: maintenance-mode.

Positive: has types; esm support; no vulnerabilities.

Warnings: low downloads.

Negative: stale; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.0.0 |
| Published | 2025-06-02 |
| First published | 2020-12-13 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 4 |
| Unpacked size | 45.7 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Arno Saine |
| Maintainers | arnosaine |

## Links

- npm: https://www.npmjs.com/package/@postinumero/use-async
- Repository: https://github.com/ArnoSaine/postinumero
- Homepage: https://github.com/ArnoSaine/postinumero/tree/main/packages/use-async
- Issues: https://github.com/ArnoSaine/postinumero/issues
- npm.io page: https://npm.io/package/@postinumero/use-async

## Dependencies (4)

- [flatted](https://npm.io/package/flatted.md) ^3.2.2
- [react-use](https://npm.io/package/react-use.md) ^17.4.0
- [fast-json-stable-stringify](https://npm.io/package/fast-json-stable-stringify.md) ^2.1.0
- [@postinumero/map-get-with-default](https://npm.io/package/@postinumero/map-get-with-default.md) ^1.0.0

## Recent versions

- 1.0.0 (latest) — 2025-06-02
- 0.3.6 — 2022-11-19
- 0.3.5 — 2022-07-27
- 0.3.4 — 2022-02-28
- 0.3.3 — 2021-12-13
- 0.3.2 — 2021-09-21
- 0.3.1 — 2021-09-20
- 0.3.0 — 2021-09-18
- 0.2.0 — 2021-09-12
- 0.1.8 — 2021-09-08
- 0.1.7 — 2021-08-31
- 0.1.6 — 2021-08-31
- 0.1.5 — 2021-08-15
- 0.1.4 — 2021-08-03
- 0.1.3 — 2021-03-17
- … 3 more at https://npm.io/package/@postinumero/use-async/versions

## README

# @postinumero/use-async

Create a suspending hook from an async function, an async generator or a function that returns an async iterator.

- Server-side rendering
- `recall` function for re-executing the function and rerendering related components from anywhere

## Examples

### Get data using axios

```js
import { Suspense } from "react";
import { create } from "@postinumero/use-async";
import axios from "axios";

const [useAxios] = create(axios);

function Todo({ id }) {
  const { data } = useAxios(`https://jsonplaceholder.typicode.com/todos/${id}`);

  return <pre>{JSON.stringify(data, null, 2)}</pre>;
}

function App() {
  return (
    <Suspense fallback="Loading...">
      <Todo id="1" />
    </Suspense>
  );
}
```

### Render timestamps with setInterval

```js
import { Suspense } from "react";
import { create } from "@postinumero/use-async";
import { Repeater } from "@repeaterjs/repeater";

const [useTimestamp] = create(
  () =>
    new Repeater(async (push, stop) => {
      push(Date.now());
      const interval = setInterval(() => push(Date.now()), 1000);
      await stop;
      clearInterval(interval);
    })
);

function Timestamp() {
  return <div>Timestamp: {useTimestamp()}</div>;
}

function App() {
  return (
    <Suspense fallback="Loading...">
      <Timestamp />
    </Suspense>
  );
}
```

## API

### `create(fn[, config])`

For creating shortcut functions of the rest of the API, without needing to pass `fn` and `config` each time.

#### Params

- `fn: AsyncFunction`
- `config`: [Config](#config) (optional)

#### Returns

An array of functions `[useAsync, recall, useAsyncSafe]`. Each of the returned function take just the `...args` as its arguments.

### `useAsync(fn[, config[, args]])`

#### Params

- `fn: AsyncFunction`
- `config`: [Config](#config) (optional)
- `args: arguments[]` for `fn` (optional)

#### Returns

Resolved value of `fn(...args)`.

#### Throws

A thrown exception from `fn` or a promise for React Suspense.

### `useAsyncSafe(fn[, config[, args]])`

#### Params

- `fn: AsyncFunction`
- `config`: [Config](#config) (optional)
- `args: arguments[]` for `fn` (optional)

#### Returns

An array `[error, value]`, where `error` is either `null` or a thrown exception from `fn(...args)`, and `value` is resolved value of `fn(...args)`.

#### Throws

Promise for React Suspense.

### `recall(fn[, config[, args]])` (async)

If there are components currently mounted using any of the hooks and the same arguments (fn, config, args), `fn(...args)` gets called. When `fn` resolves, components will rerender with the new value.

#### Params

- `fn: AsyncFunction`
- `config`: [Config](#config) (optional)
- `args: arguments[]` for `fn` (optional)

#### Returns

Resolves with `undefined`, when `fn(...args)` resolves.

## Config

| Prop | Example   | Default value | Description                                                          |
| ---- | --------- | ------------- | -------------------------------------------------------------------- |
| `id` | `"axios"` | `undefined`   | Cache values using `id` as key instead of `fn`. **Required in SSR.** |

## Server-side Rendering

1. Use `createSSRCache` to get `SSRCacheProvider` and `ssrData`
2. Wrawp server-side `<App>` with `<SSRCacheProvider>`
3. Use `react-ssr-prepass` to handle suspense
4. Get initial SSR data using `ssrData()`. `ssrData` accepts a `map` function, which is called for each data entry with 2 arguments: `data`, `{ id, args }`.
5. Place the data in a `<script>` before the application

```js
import { /* nothing, */ createSSRCache } from "@postinumero/use-async";
import ssrPrepass from "react-ssr-prepass";

//...

const { ssrData, SSRCacheProvider } = createSSRCache();

const element = (
  <SSRCacheProvider>
    <App />
  </SSRCacheProvider>
);
await ssrPrepass(element);

const app = ReactDOMServer.renderToString(element);

res.send(
  html.replace(
    '<div id="root"></div>',
    `<script>${ssrData(([error, response]) =>
      // error ? nothing :
      [
        error,
        response && {
          data: response.data,
          headers: response.headers,
          status: response.status,
        },
      ]
    )}</script><div id="root">${app}</div>`
  )
);
```

## Not ready for Suspense?

Import from `@postinumero/use-async/loading-state` to use the `{ isLoading, data, error }` style API. Example:

```js
import { create } from "@postinumero/use-async/loading-state";
import axios from "axios";

const [, , useAxiosSafe] = create(axios);

function User({ id }) {
  const { isLoading, data, error } = useAxiosSafe(`/api/users/${id}`);

  if (isLoading) {
    return "Loading...";
  }

  return <div>First name: {data.data.first_name}</div>;
}
```

---
_Source: https://npm.io/package/@postinumero/use-async · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
