useAsync

This custom hook allows you to handle asynchronous operations in a declarative way. It takes an asynchronous function as an input and returns an object with three properties:

  • isLoading: A boolean indicating whether the async operation is currently in progress.
  • error: An error object, if an error occurred during the async operation.
  • result: The result of the async operation.
import { useState, useEffect } from 'react'

function useAsync(asyncFunction) {
  const [data, setData] = useState(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState(null)

  useEffect(() => {
    async function fetchData() {
      setLoading(true)
      try {
        const response = await asyncFunction()
        setData(response)
      } catch (e) {
        setError(e)
      } finally {
        setLoading(false)
      }
    }

    fetchData()
  }, [asyncFunction])

  return { data, loading, error }
}

To use the useAsync hook, you simply pass in your asynchronous function as an argument:

async function fetchData() {
  const response = await fetch(
    'https://pokeapi.co/api/v2/pokemon?limit=100&offset=0'
  )
  return response.json()
}

function MyComponent() {
  const { isLoading, error, data } = useAsync(fetchData)

  if (isLoading) {
    return <div>Loading...</div>
  }

  if (error) {
    return <div>Error: {error.message}</div>
  }

  console.log(data)

  return (
    <div>
      {data?.results.map((item, index) => {
        return <div key={index}>{item.name}</div>
      })}
    </div>
  )
}

In this example, we call the useAsync hook with an asynchronous function called fetchData. We then use the isLoading and error variables to conditionally render a loading spinner or an error message. Finally, we display the result when it is available.

To use this hook in your project, you can simply copy the code and use it as a custom hook in your React components.

Codesandbox Example