No async Client Component
Source URL: https://nextjs.org/docs/messages/no-async-client-component
No async Client Component
Section titled “No async Client Component”Client components cannot be async functions.
Why This Error Occurred
Section titled “Why This Error Occurred”The error occurs when you try to define a Client Component as an async function. React Client Components do not support async functions. For example:
'use client'
// This will cause an errorasync function ClientComponent() { // ...}Possible Ways to Fix It
Section titled “Possible Ways to Fix It”- Convert to a Server Component: If possible, convert your Client Component to a Server Component. This allows you to use
async/awaitdirectly in your component. - Remove the
asynckeyword: If you need to keep it as a Client Component, remove theasynckeyword and handle data fetching differently. - Use React Hooks for data fetching: Utilize hooks like
useEffectfor client-side data fetching, or use third-party libraries. - Leverage the
useAPI with a Context Provider: Pass promises to child components using context, then resolve them with theuseAPI.
Recommended: Server-side data fetching
Section titled “Recommended: Server-side data fetching”We recommend fetching data on the server. For example:
export default async function Page() { const data = await fetch('https://api.vercel.app/blog') const posts = await data.json() return ( <ul> {posts.map((post) => ( <li key={post.id}>{post.title}</li> ))} </ul> )}Using use with Context Provider
Section titled “Using use with Context Provider”Another pattern to explore is using the React use API with a Context Provider. This allows you to pass Promises to child components and resolve them using the use API . Here’s an example:
First, let’s create a separate file for the context provider:
'use client'
import { createContext, useContext } from 'react'
export const BlogContext = createContext<Promise<any> | null>(null)
export function BlogProvider({ children, blogPromise,}: { children: React.ReactNode blogPromise: Promise<any>}) { return ( <BlogContext.Provider value={blogPromise}>{children}</BlogContext.Provider> )}
export function useBlogContext() { const context = useContext(BlogContext) if (!context) { throw new Error('useBlogContext must be used within a BlogProvider') } return context}Now, let’s create the Promise in a Server Component and stream it to the client:
import { BlogProvider } from './context'
export default function Page() { const blogPromise = fetch('https://api.vercel.app/blog').then((res) => res.json() )
return ( <BlogProvider blogPromise={blogPromise}> <BlogPosts /> </BlogProvider> )}Here is the blog posts component:
'use client'
import { use } from 'react'import { useBlogContext } from './context'
export function BlogPosts() { const blogPromise = useBlogContext() const posts = use(blogPromise)
return <div>{posts.length} blog posts</div>}This pattern allows you to start data fetching early and pass the Promise down to child components, which can then use the use API to access the data when it’s ready.
Client-side data fetching
Section titled “Client-side data fetching”In scenarios where client fetching is needed, you can call fetch in useEffect (not recommended), or lean on popular React libraries in the community (such as SWR or React Query) for client fetching.
'use client'
import { useState, useEffect } from 'react'
export function Posts() { const [posts, setPosts] = useState(null)
useEffect(() => { async function fetchPosts() { const res = await fetch('https://api.vercel.app/blog') const data = await res.json() setPosts(data) } fetchPosts() }, [])
if (!posts) return <div>Loading...</div>
return ( <ul> {posts.map((post) => ( <li key={post.id}>{post.title}</li> ))} </ul> )}