# useAsyncFn (https://docs.salla.dev/twilight/react/hooks/use-async-fn)



Use `useAsyncFn` when a button or form runs an async action and you need a `loading` flag, the result or the error, without writing that state yourself.

## Example [#example]

```tsx title="app/components/product/SaveForLater.tsx"
import { useAsyncFn } from '@salla.sa/twilight-theme-engine/hooks/useAsyncFn';

export function SaveForLater({ productId }: { productId: number }) {
  const [state, save] = useAsyncFn(async () => {
    await window.salla?.wishlist.add(productId);
    return true;
  }, [productId]);

  return (
    <button onClick={() => save()} disabled={state.loading}>
      {state.value ? 'Saved' : 'Save for later'}
    </button>
  );
}
```

It returns a pair: the current state, and a wrapped version of your function. Call the wrapped function to run the action.

## API [#api]

```ts
function useAsyncFn<T extends (...args: never[]) => Promise<unknown>>(
  fn: T,
  deps?: DependencyList,
  initialState?: AsyncState<Awaited<ReturnType<T>>>
): [AsyncState<Awaited<ReturnType<T>>>, T];
```

| Prop            | Type             | Description                                                               |
| --------------- | ---------------- | ------------------------------------------------------------------------- |
| `fn`            | `T`              | The async function to wrap. Required.                                     |
| `deps?`         | `DependencyList` | Values `fn` reads, like the dependencies of `useCallback`. Default: `[]`. |
| `initialState?` | `AsyncState`     | Starting state. Default: `{ loading: false }`.                            |

The state has `loading: boolean`, and then `value` after success or `error` after failure.

## Gotchas [#gotchas]

<Callout type="warn">
  When `fn` rejects, the wrapped function does not throw. It resolves with the error, and `state.error` is set. Check `state.error` or `result instanceof Error` instead of using `try/catch`.
</Callout>

* `deps` defaults to `[]`, so the wrapped function keeps the first `fn` it saw. Pass every value `fn` reads, as in the example.
* Only the latest call updates the state. Results of older, slower calls are ignored.
* State is not updated after the component unmounts.

## Next [#next]

* [`useWishlist`](https://docs.salla.dev/twilight/react/hooks/use-wishlist) is built on this hook.
* [Loading data](https://docs.salla.dev/twilight/react/guide/loading-data) covers data that belongs in a route loader instead.
* [Salla SDK and events](https://docs.salla.dev/twilight/react/guide/salla-sdk-and-events) lists the `Salla.*` calls you will wrap.
