LogoLogo
HomeDocsGitHubDiscord
next
next
  • Introduction
  • Getting started
    • Installation
    • Upgrading
    • Usage
    • DevTools
  • API
    • Interfaces
    • Configuration options
    • State properties
    • Helper components
  • Guide
    • Async components
    • Separating view and logic
    • Async actions
    • Optimistic updates
    • Server-side rendering
  • Contributing
    • Introduction
    • Setting up
    • Development
    • Testing
    • Releasing
Powered by GitBook
On this page
  • Creating an async component with useFetch
  • More flexibility with useAsync

Was this helpful?

  1. Guide

Async components

PreviousHelper componentsNextSeparating view and logic

Last updated 5 years ago

Was this helpful?

The most common use case for React Async is data fetching. In single-page applications it's very common to dynamically load some data from a backend. React Async makes it incredibly easy to set this up, without having to worry about the details.

The mental model of React Async is component-first. Rather than loading data high up in your application and passing it down to a component for display, you perform the data loading at the component level. Such a component is called an async component. An async component can render its state in a meaningful way like any other component, or be logic-only. In that case it doesn't render any UI but instead passes its state down to its children. Such separation of concerns is good practice.

Creating an async component with useFetch

The easiest way to create an async component for data fetching is through the :

import React from "react"
import { useFetch } from "react-async"

const Person = ({ id }) => {
  const { data, error } = useFetch(`https://swapi.co/api/people/${id}/`, {
    headers: { accept: "application/json" },
  })
  if (error) return error.message
  if (data) return `Hi, my name is ${data.name}!`
  return null
}

const App = () => {
  return <Person id={1} />
}

More flexibility with useAsync

The above example, written with useAsync, would look like this:

import React from "react"
import { useAsync } from "react-async"

const fetchPerson = async ({ id }, { signal }) => {
  const response = await fetch(`https://swapi.co/api/people/${id}/`, { signal })
  if (!response.ok) throw new Error(response.status)
  return response.json()
}

const Person = ({ id }) => {
  const { data, error } = useAsync({ promiseFn: fetchPerson, id })
  if (error) return error.message
  if (data) return `Hi, my name is ${data.name}!`
  return null
}

const App = () => {
  return <Person id={1} />
}

For most data fetching needs, useFetch is sufficient. However, sometimes you may want to take full control, for example if you want to combine multiple requests. In this case you can use the .

The core concept of useAsync (and React Async in general), is the : a function that returns a Promise. It's the fundamental concept for modelling asynchronous operations. It enables React Async to take control over scheduling, the Promise lifecycle and things like (re)starting an operation on user action or other changes. We've deliberately chosen the Promise as our primitive, because it's natively supported and has various utility methods like Promise.all. That's also why you'll find our terminology closely follows the Promise .

Notice the incoming parameters to fetchPerson. The promiseFn will be invoked with a props object and an AbortController. props are the options you passed to useAsync, which is why you can access the id property using . The AbortController is created by React Async to enable , so the underlying request will be aborted when the promise is cancelled (e.g. when a new one starts or we leave the page). We have to pass its AbortSignal down to fetch in order to wire this up.

useFetch hook
useAsync hook
promiseFn
states and fates
object destructuring
abortable fetch