DEV Community

Francisldn
Francisldn

Posted on

5 1

React Data Fetching Patterns - Part I

In React, data fetching from an external API typically involves a few steps, as below:

  1. send a fetch request
  2. await for response
  3. receive the requested data or error

In this article, we will first discuss how data fetching is traditionally done in React using useState-useEffect hooks. We will then proceed to discuss other data fetching patterns, utilising Suspense - an API made available in React v18 (no longer experimental), as follows:

Click here to access the Github repo for the code examples discussed below.

How data fetching is traditionally done

In React, we traditionally perform data fetching using useState-useEffect hooks. Within a React component, a state is created using useState hook to store data. useEffect hook is executed as the component first mounts or page first renders. The data fetching logic in the useEffect hook will run and data will be stored as a state.

Let's go through the code:

  • users state is declared with useState, together with loading and error states
  • Within useEffect, getUsers function will execute on component mounts, and the loading state will set to true while waiting for data to be retrieved
  • On successful data retrieval, the loading and error states will set to false, and users state will contain the retrieved data, ready for UI rendering.
export default function CardList() {
    const [users, setUsers] = useState<User[]>([])
    const [isLoading, setLoading] = useState(false)
    const [isError, setError] = useState(false)

    useEffect(() => { 
        setLoading(true)  
        getUsers(apiURL)
            .then(({results:data}) => {
                setUsers(
                data.map((user:UserApi) => {
                    return {
                        id: user.id.value,
                        firstName: user.name.first,
                        lastName: user.name.last,
                        username: user.login.username,
                        email: user.email,
                    }}))
                })
            .catch(() => setError(true))
            .finally(() => setLoading(false))
    },[])

  return (
    <div className="grid sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 justify-center grid-cols-1 mt-8">
        {isLoading 
        ? <Loading />
        : isError 
        ? <ErrorFallBack />
        : users.map((user:User) => (<CardItem key={user.id} user={user}/>))
        }
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Downsides

Prop-drilling
While this data fetching pattern works fine for a local component, if there were multiple components that require access to the same set or a subset of the data, then we will need to pass the props through multiple child components, which could lead to problems of prop-drilling. For a larger app, prop-drilling through multiple layers of components can make the app unwieldy and hard to manage.

To overcome the issues outlined above, let's proceed to look at a few other data fetching methods, as below.

To be continued:

If you like the content, please hit the like button so that it can reach more people.

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (1)

Collapse
 
jim462 profile image
Jim • • Edited

"To be continued" wtf? It's 2 years later. Where is it?

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs