Skip to content

Instantly share code, notes, and snippets.

@AlperRehaYAZGAN
Created April 7, 2025 11:23
Show Gist options
  • Save AlperRehaYAZGAN/7ad515fa037ae88c68bff910522275a3 to your computer and use it in GitHub Desktop.
Save AlperRehaYAZGAN/7ad515fa037ae88c68bff910522275a3 to your computer and use it in GitHub Desktop.

React 19 use() Hook — Async Functions in Client Components Made Easy

Hello everyone! In today's post, we'll explore the use() hook introduced with React v19. This innovation allows frontend developers to easily use async functions without needing boilerplate code or external libraries (like React Query).

Reference Links

Technologies Used

  • Next.js v15 - App Directory
  • React v19 - "use(), Suspense"
  • Tailwindcss

What is the use() Hook?

As React Frontend developers, with Remix.js and Next.js v14, we were introduced to "React Server Components" and their server-side implementations. In traditional React development, our code and interface components went through a bundling process during build time and were sent to users as a "Client Bundle". These bundles were executed and rendered as JavaScript in the user's browser.

This process changed with React Server Components. Now our components are rendered on the server and sent to the client ready to use. This provides:

  • Less JavaScript code running on the client
  • Faster user experience
  • Smaller client bundle sizes
  • Easier error handling on the server side

However, using async functions became more complicated in this process. You either needed to use the useEffect hook or external libraries. Thanks to the use() hook introduced with React v19, we can now easily use async functions in Client Components.

Demo: Calling Server Action from Client Component

As an example, we'll create a "People You May Know" list page for our site users. On this /profiles page, we'll fetch user profiles through a "Server Action" running on our server and display them in the interface using a client component.

First, let's write our user fetching function:

"use server";

// filepath: /app/profiles/action.ts
export async function getLatestUsers() {
  // 3 seconds delay simulation
  const wait3Sec = new Promise((resolve) => setTimeout(resolve, 3000));
  await wait3Sec;

  const data = await fetch("https://jsonplaceholder.typicode.com/users");
  const users = await data.json();
  return users;
}

After writing our async API call that will run on the server, let's create our page with Next.js and transfer this call from server to client side using React Suspense:

"use server";

import { Suspense, use } from "react";
import { getLatestUsers } from "./action";
import { UsersList } from "./users-list.component";

// filepath: /app/profiles/page.tsx
export default async function ProfilesPage() {
  // no need to use await
  const usersPromise = getLatestUsers();

  return (
    <div>
      <Suspense
        fallback={
          <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500" />
        }
      >
        <UsersList usersPromise={usersPromise} />
      </Suspense>
    </div>
  );
}

Notice that we no longer need to use await. With React v19, we can directly pass Promises to the client side. Our Client Component will start populating the screen when the API response arrives. React understands that this call is a Promise and will show the "Suspense Fallback" component until the server response arrives. When the response comes, it will render the <UserList usersPromise={usersPromise} /> component.

Now let's create our client-side UsersList component that React will render when the data arrives:

"use client";

import { use } from "react";

// filepath: /app/profiles/users-list.component.tsx
export function UsersList({ usersPromise }: { usersPromise: Promise<any[]> }) {
  // We can directly pass the Promise as a parameter to the use() hook
  const users = use(usersPromise);

  return (
    <div>
      <h2 className="text-xl font-semibold mb-3">Latest Users</h2>
      <ul className="divide-y divide-gray-100">
        {users.map((user) => (
          <li key={user.id} className="flex items-center p-3 gap-3">
            <div className="flex-1 min-w-0">
              {user.id} - {user.username} - {user.email}
            </div>
          </li>
        ))}
      </ul>
    </div>
  );
}

Demo Image

[Demo image to be added]

Conclusion

With this demo, we explored the use() hook introduced with React v19 that has reached stable release. Thanks to this hook, we can now directly use Promises in Client Components.

See you next time 👋

Alper R. Yazgan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment