/
githubmirror
/
next.js
Обзор
Документация
Войти
/
githubmirror
/
next.js
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
canary
errors/no-async-client-component.mdx
146 строк
4 KB
Vasiliy Vanchuk
docs: correct use term (#89438)
11 фев 2026, 13:51
Не верифицирован
11 фев 2026, 13:51
be56ce3
Код
Авторство
О чём код?
--- title: No async Client Component --- > Client components cannot be async functions. ## 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](https://github.com/acdlite/rfcs/blob/first-class-promises/text/0000-first-class-support-for-promises.md#why-cant-client-components-be-async-functions) async functions. For example: ```tsx 'use client' // This will cause an error async function ClientComponent() { // ... } ``` ## Possible Ways to Fix It 1. **Convert to a Server Component**: If possible, convert your Client Component to a Server Component. This allows you to use `async`/`await` directly in your component. 2. **Remove the `async` keyword**: If you need to keep it as a Client Component, remove the `async` keyword and handle data fetching differently. 3. **Use React Hooks for data fetching**: Utilize hooks like `useEffect` for client-side data fetching, or use third-party libraries. 4. **Leverage the `use` API with a Context Provider**: Pass promises to child components using context, then resolve them with the `use` API. ### Recommended: Server-side data fetching We recommend fetching data on the server. For example: ```tsx filename="app/page.tsx" 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 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: ```tsx filename="app/context.tsx" '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: ```tsx filename="app/page.tsx" 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: ```tsx filename="app/blog-posts.tsx" '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 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](https://swr.vercel.app/) or [React Query](https://tanstack.com/query/latest)) for client fetching. ```tsx filename="app/page.tsx" '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> ) } ```