nextjs component_error ai_generated true

Error: async/await is not yet supported in Client Components, only Server Components.

ID: nextjs/async-client-component

Also available as: JSON · Markdown
93%Fix Rate
94%Confidence
80Evidence
2023-01-01First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
14 active

Root Cause

A component marked with 'use client' uses async/await at the component level. Client Components cannot be async functions. Data fetching must use useEffect, Server Actions, or the data should be fetched in a Server Component parent.

generic

Workarounds

  1. 94% success Move the async data fetching into useEffect with useState
    'use client';
    import { useState, useEffect } from 'react';
    
    export default function MyComponent() {
      const [data, setData] = useState(null);
      useEffect(() => {
        async function fetchData() {
          const res = await fetch('/api/data');
          setData(await res.json());
        }
        fetchData();
      }, []);
      if (!data) return <div>Loading...</div>;
      return <div>{data.title}</div>;
    }

    Sources: https://nextjs.org/docs/app/building-your-application/data-fetching/fetching#fetching-data-on-the-client

  2. 95% success Fetch data in a Server Component parent and pass it as props
    // page.tsx (Server Component, no 'use client')
    import { ClientComponent } from './ClientComponent';
    export default async function Page() {
      const data = await fetch('https://api.example.com/data').then(r => r.json());
      return <ClientComponent data={data} />;
    }
    
    // ClientComponent.tsx
    'use client';
    export function ClientComponent({ data }) {
      const [state, setState] = useState(data);
      return <div>{state.title}</div>;
    }

    Sources: https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#moving-client-components-down-the-tree

  3. 89% success Use a Server Action for on-demand data fetching from the client
    // actions.ts
    'use server';
    export async function getData(id: string) {
      const res = await fetch(`https://api.example.com/data/${id}`);
      return res.json();
    }
    
    // ClientComponent.tsx
    'use client';
    import { getData } from './actions';
    import { useTransition } from 'react';
    
    export function ClientComponent() {
      const [isPending, startTransition] = useTransition();
      const [data, setData] = useState(null);
      const handleClick = () => {
        startTransition(async () => {
          const result = await getData('123');
          setData(result);
        });
      };
    }

    Sources: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations

Dead Ends

Common approaches that don't work:

  1. Remove the 'use client' directive to make it a Server Component 75% fail

    If the component uses React hooks (useState, useEffect, useRef) or browser APIs (window, document, localStorage), removing 'use client' will trigger hook/browser API errors. The component is a Client Component for a reason.

  2. Use a top-level await inside the client component body 95% fail

    Top-level await is a module-level feature and cannot be used inside React component functions. React component rendering must be synchronous in Client Components.

  3. Wrap the async component in Suspense to make it work as a client component 88% fail

    Suspense boundaries handle loading states for lazy-loaded or server components, but they do not enable async/await syntax in Client Component function bodies. The component function itself still cannot be async.

Error Chain

Leads to:
Preceded by:
Frequently confused with: