You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: errors/no-async-client-component.mdx
+135-3Lines changed: 135 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,9 +6,141 @@ title: No async client component
6
6
7
7
## Why This Error Occurred
8
8
9
-
As per the [React Server Component RFC on promise support](https://github.com/acdlite/rfcs/blob/first-class-promises/text/0000-first-class-support-for-promises.md), [client components cannot be async functions](https://github.com/acdlite/rfcs/blob/first-class-promises/text/0000-first-class-support-for-promises.md#why-cant-client-components-be-async-functions).
9
+
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:
10
+
11
+
```tsx
12
+
'use client'
13
+
14
+
// This will cause an error
15
+
asyncfunction ClientComponent() {
16
+
// ...
17
+
}
18
+
```
10
19
11
20
## Possible Ways to Fix It
12
21
13
-
1. Remove the `async` keyword from the client component function declaration, or
14
-
2. Convert the client component to a server component
22
+
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.
23
+
2.**Remove the `async` keyword**: If you need to keep it as a client component, remove the `async` keyword and handle data fetching differently.
24
+
3.**Use React hooks for data fetching**: Utilize hooks like `useEffect` for client-side data fetching, or use third-party libraries.
25
+
4.**Leverage the `use` hook with a Context Provider**: Pass promises to child components using context, then resolve them with the `use` hook.
26
+
27
+
### Recommended: Server-side data fetching
28
+
29
+
We recommend fetching data on the server. For example:
30
+
31
+
```tsx filename="app/page.tsx"
32
+
exportdefaultasyncfunction Page() {
33
+
let data =awaitfetch('https://api.vercel.app/blog')
34
+
let posts =awaitdata.json()
35
+
return (
36
+
<ul>
37
+
{posts.map((post) => (
38
+
<likey={post.id}>{post.title}</li>
39
+
))}
40
+
</ul>
41
+
)
42
+
}
43
+
```
44
+
45
+
### Using `use` with Context Provider
46
+
47
+
Another pattern to explore is using the React `use` hook with a Context Provider. This allows you to pass Promises to child components and resolve them using the `use` hook . Here's an example:
48
+
49
+
First, let's create a separate file for the context provider:
thrownewError('useBlogContext must be used within a BlogProvider')
74
+
}
75
+
returncontext
76
+
}
77
+
```
78
+
79
+
Now, let's create the Promise in a Server Component and stream it to the client:
80
+
81
+
```tsx filename="app/page.tsx"
82
+
import { BlogProvider } from'./context'
83
+
84
+
exportdefaultfunction Page() {
85
+
let blogPromise =fetch('https://api.vercel.app/blog').then((res) =>
86
+
res.json()
87
+
)
88
+
89
+
return (
90
+
<BlogProviderblogPromise={blogPromise}>
91
+
<BlogPosts />
92
+
</BlogProvider>
93
+
)
94
+
}
95
+
```
96
+
97
+
Here is the blog posts component:
98
+
99
+
```tsx filename="app/blog-posts.tsx"
100
+
'use client'
101
+
102
+
import { use } from'react'
103
+
import { useBlogContext } from'./context'
104
+
105
+
exportfunction BlogPosts() {
106
+
let blogPromise =useBlogContext()
107
+
let posts =use(blogPromise)
108
+
109
+
return <div>{posts.length} blog posts</div>
110
+
}
111
+
```
112
+
113
+
This pattern allows you to start data fetching early and pass the Promise down to child components, which can then use the `use` hook to access the data when it's ready.
114
+
115
+
### Client-side data fetching
116
+
117
+
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.
118
+
119
+
```tsx filename="app/page.tsx"
120
+
'use client'
121
+
122
+
import { useState, useEffect } from'react'
123
+
124
+
exportfunction Posts() {
125
+
let [posts, setPosts] =useState(null)
126
+
127
+
useEffect(() => {
128
+
asyncfunction fetchPosts() {
129
+
let res =awaitfetch('https://api.vercel.app/blog')
0 commit comments