DEV Community

Alex Chiu
Alex Chiu

Posted on • Originally published at chiubaca.com

Easy React data fetching with the new `use()` hook

React.use() is still an unstable API. For more information check out the support for promises React RFC . At the time of writing this, you can only test this API in Next.js 13.

OK with that disclaimer out the way, lets talk about how use() works .

In short, this new hook will let you you run asynchronous code in your client-side react components. You can think of it as the React version of async / await.

To appreciate why it's going to be a game changer for client side data-fetching, lets compare the old-way of doing a client-side data fetch using useEffect() with use().

// returns an array of user objects e.g:
// [ {id:1 name: "Leanne Graham"}, {id:1 name: "Ervin Howell"}] 

export const fetchUsers = async () => {
  const resp = await 
  fetch("https://jsonplaceholder.typicode.com/users");
  const json = await resp.json();
  return json; 
};

Enter fullscreen mode Exit fullscreen mode
'use client'

import { useState, useEffect } from "react";
import { fetchUsers } from "@/fetch-users";


export const OldDataFetchData = () => {

const [usersData, setUsersData] = useState(null);


useEffect(() => {
    if (!usersData) {
        const startFetchingData = async () => {
            const users = await fetchUsers();
            setUsersData(users);
        };
           startFetchingData();
    }

    }, [usersData]);



    if (!usersData) {
        return <>Loading...</>;
    }

    return (
        <>
            {usersData.map((u) => (
                <div key={u.id}>{u.name} </div>
            ))}

        </>
    );

};

Enter fullscreen mode Exit fullscreen mode

This is idiomatic code for most React developers. But for those less familiar with React and useEffect you may ask all sort of questions like:

  • Why cant the function you pass into useEffect be async?
  • Why cant the whole React component be async?
  • Why do you need to check userData before calling startFetchingData()?

There are technical answers to all of these,but this is not a useEffect tutorial so a quick response would be - because, React. 😅

My point is, this is not intuitive code to read but we React developers have become accustomed to the rules and quirks of useEffect.

Now lets see how can re-write this with use() .

'use client'

import { use } from "react";
import { fetchUsers } from "@/fetch-users";

export const NewDataFetchData = () => {

const usersData = use(fetchUsers());

return (
    <>
        {usersData.map((u) => (
            <div key={u.id}>{u.name} </div>
        ))}
    </>
);

};
Enter fullscreen mode Exit fullscreen mode

Thats's it!

Ok I lied.

A little bit more code is required If you want to handle a loading state. In the parent server component that uses this client component, you can wrap it in Suspense which can accept a React component in its fallback prop.

// ./app/page.jsx

import { Suspense } from "react";
import { NewDataFetchData } from "@/components/NewDataFetch";  

export default function Home() {
    return (
        <main>
            <Suspense fallback={<>Loading...</>}>
                <NewDataFetchData />
            </Suspense>
        </main>
    );
}
Enter fullscreen mode Exit fullscreen mode

Overall, much more elegant to read and write.


An interesting property of the use hook is that it can be called conditionally 🤯.

This is a big deal because we've traditionally never been able to usehooks conditionally.

Here is an example of how this could look taken from the rfc.

function Note({id, shouldIncludeAuthor}) {
  const note = use(fetchNote(id));

  let byline = null;
  if (shouldIncludeAuthor) {
    const author = use(fetchNoteAuthor(note.authorId));
    byline = <h2>{author.displayName}</h2>;
  }

  return (
    <div>
      <h1>{note.title}</h1>
      {byline}
      <section>{note.body}</section>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

I'm excited for this hook to become stable but I have mixed emotions.

On one hand, the ergonomics of data fetching will be so much better and we may no longer need to rely of a third party libraries like TanStack query.

On the other hand, our mental model of hooks needs to adjust when using use(), maybe this is not a big deal, but I can see this being a point of confusion for beginner React devs.

If you want to test out the use() for yourself, feel free to fork this codesandbox which is running the code examples above.

Top comments (0)