@react-hook/async

A React hook for gracefully resolving async functions and promises

Usage no npm install needed!

<script type="module">
  import reactHookAsync from 'https://cdn.skypack.dev/@react-hook/async';
</script>

README


useAsync()

Bundlephobia Types Build status NPM Version MIT License

npm i @react-hook/async

A React hook for gracefully resolving, cancelling, and handling errors for async functions and promises. These hooks also clean up any lingering promises when your component unmounts by cancelling them.

Quick Start

Check out the example on CodeSandbox

import {useAsync, useAsyncEffect} from '@react-hook/async'

// Example using a manual invocation
const CallbackResolver = () => {
  const [{status, cancel, error, value}, call] = useAsync(() => {
    return new Promise((resolve) => setTimeout(() => resolve('Loaded'), 3000))
  })

  switch (status) {
    case 'loading':
      return (
        <div>
          <button onClick={cancel}>Cancel</button>
          Loading...
        </div>
      )
    case 'cancelled':
      return (
        <div>
          Cancelled.
          <button onClick={call}>Try again</button>
        </div>
      )
    case 'error':
      return `Error: ${error}`
    case 'success':
      return value || 'Success!'
    default:
      return <button onClick={call}>Load me</button>
  }
}

// Example using a useEffect invocation
const EffectResolver = () => {
  const [curr, setCurr] = useState(0)
  // Will load each time counter changes
  const {status, cancel, error, value} = useAsyncEffect(() => {
    return new Promise((resolve) =>
      setTimeout(() => resolve(`Loaded ${curr}`), 3000)
    )
  }, [curr])

  switch (status) {
    case 'loading':
      return (
        <div>
          <button onClick={cancel}>Cancel</button>
          Loading...
        </div>
      )
    case 'cancelled':
      return (
        <div>
          Cancelled.
          <button onClick={() => setCurr((curr) => ++curr)}>Try again</button>
        </div>
      )
    case 'error':
      return `Error: ${error}`
    case 'success':
      return (
        <div>
          {value}
          <button onClick={() => setCurr((curr) => ++curr)}>Load again</button>
        </div>
      )
    default:
      return null
  }
}

API

useAsync(asyncCallback)

export const useAsync = <
  ValueType extends any = any,
  ErrorType extends any = Error,
  Args extends any[] = any[]
>(
  asyncCallback: (...args: Args) => Promise<ValueType>
): [AsyncState<ValueType, ErrorType, Args>, AsyncCallback<Args>]

Arguments

Argument Type Default Required? Description
asyncCallback (...args: Args) => Promise<ValueType> undefined Yes An async function or function that returns a promise.

Returns [AsyncState<ValueType, ErrorType>, AsyncCallback]


AsyncState

export interface AsyncState<ValueType, ErrorType> {
  // 'idle' | 'loading' | 'success' | 'error' | 'cancelled'
  status: AsyncStatus
  // The return value of your async callback or promise. This value is persisted until there
  // is another successful promise resolution. That means you when you're in an 'error', 'loading',
  // or 'cancelled' state, you'll still have the most recent successful value here. This is useful
  // because the status property should be dictating what you're doing in your UI and there are
  // cases where you won't want to lose the current value.
  value?: ValueType
  // The error object from any exceptions encountered inside the async function
  // or the value of the promise rejection.
  error?: ErrorType
  // Cancels the promise
  cancel: () => void
}

AsyncCallback

export interface AsyncCallback<Args extends any[] = any[]> {
  (...args: Args): void
  cancel: () => void
}

useAsyncEffect(asyncCallback, dependencies)

export const useAsyncEffect = <
  ValueType extends any = any,
  ErrorType extends any = Error
>(
  asyncCallback: () => Promise<ValueType>,
  dependencies?: React.DependencyList
): AsyncState<ValueType, ErrorType, []>

This hook will invoke a callback each time its dependencies array changes.

Arguments

Argument Type Default Required? Description
asyncCallback () => Promise<ValueType> undefined Yes An async function or function that returns a promise.
dependencies any[] undefined No Values or state that your callback depends on. This works the same as the dependencies array of useEffect, useCallback, etc.

Returns AsyncState<ValueType, ErrorType>

LICENSE

MIT