afaqrashid.com  ·  portfolio · 2026 ed.

"async/await is not yet supported in Client Components" in Next.js: What Breaks and the Fix, Tested

Only Server Components can be async functions. If a file has "use client" at the top and its component is async, React complains. Older React versions said "async/await is not yet supported in Client Components, only Server Components". On Next.js 16.4.4 with React 19.3 the message is:

<Page> is an async Client Component. Only Server Components can be async at the moment.
This error is often caused by accidentally adding `'use client'` to a module that was
originally written for the server.

The fix is to remove "use client" from the async component and move the interactive part into a small client component, or to pass a promise from the server and read it with use(). Both are below. First, what actually goes wrong, because it's easy to miss.

What I tested

"use client";

export default async function Page() {
  const res = await fetch("https://example.com", { cache: "no-store" });
  return <p>status {res.status}</p>;
}
  • next build: passed, with no error or warning.
  • Loading the page directly, in dev and production: it rendered "status 200", because the server rendered it and sent the HTML.
  • next dev: the error above appeared as a Console Error in the Next.js overlay, not as a crash.
  • next start (production): no error at all in the browser console.
  • Clicking a <Link> to the page from another page, in production: nothing happened. After 15 seconds the URL hadn't changed and there was still no error. A link to a normal client page next to it navigated straight away.

So the page looks fine when you open it by URL and when you test the build, and the bug shows up as "the link doesn't work". If a link in your app seems dead, check whether the page it points to is an async client component.

Fix 1: keep the async part on the server

Usually "use client" was added because something in the page needs state or a click handler. Move only that into its own file:

// app/aa-fix1/page.tsx (Server Component, no "use client")
import LikeButton from "./like-button";

export default async function Page() {
  const res = await fetch("https://example.com", { cache: "no-store" });
  return (
    <div>
      <p>status {res.status}</p>
      <LikeButton />
    </div>
  );
}

// app/aa-fix1/like-button.tsx
"use client";
import { useState } from "react";

export default function LikeButton() {
  const [n, setN] = useState(0);
  return <button onClick={() => setN(n + 1)}>likes {n}</button>;
}

Navigating to it with a Link worked, it showed status 200, and the button counted clicks. If you remove "use client" from a component that still calls useState, you get a different build error, covered in You're importing a component that needs useState.

Fix 2: pass a promise and read it with use()

If the component that needs the data has to be a client component, start the request on the server without awaiting it, pass the promise down, and read it with React's use() inside a Suspense boundary:

// app/aa-fix2/page.tsx (Server Component)
import { Suspense } from "react";
import Status from "./status";

export default function Page() {
  const statusPromise = fetch("https://example.com", { cache: "no-store" }).then((r) => r.status);
  return (
    <Suspense fallback={<p>Loading…</p>}>
      <Status statusPromise={statusPromise} />
    </Suspense>
  );
}

// app/aa-fix2/status.tsx
"use client";
import { use } from "react";

export default function Status({ statusPromise }: { statusPromise: Promise<number> }) {
  const status = use(statusPromise);
  return <p>status {status}</p>;
}

This rendered status 200 on a direct load and after a Link navigation. Create the promise in the Server Component, not inside the client component: a promise created during a client render is a new one on every render.

Other options

  • Fetch in useEffect inside a normal (non-async) client component, with a loading state. It works, but the data arrives only after the JavaScript runs, so the first HTML has no data.
  • Use a data library such as SWR or TanStack Query in the client component, which handles loading, caching and refetching for you.
  • If the code only needs to run once on the server (database, secrets), it belongs in a Server Component or a Server Action, not a client component at all.

Quick checklist

  • Search for files that contain both "use client" and export default async function (or an async arrow component).
  • Look in the dev overlay for "is an async Client Component"; production won't tell you.
  • Test pages by clicking links to them, not only by opening the URL.

Related

Sources