Async/Await Client Component
Unanswered
Scottish Fold posted this in #help-forum
Scottish FoldOP
I am getting the following error.
async/await is not yet supported in Client Components, only Server Components. This error is often caused by accidentally adding 'use client' to a module that was originally written for the server.
Even though I have not used an async function as a component. After refreshing the page the error goes away.
Using next: 14.0.4
async/await is not yet supported in Client Components, only Server Components. This error is often caused by accidentally adding 'use client' to a module that was originally written for the server.
Even though I have not used an async function as a component. After refreshing the page the error goes away.
Using next: 14.0.4
59 Replies
We can't help you if you don't provide the code for the component that's causing the error and how you structured your app. A general outline should be enough.
That said, sometimes barrel files can cause this type of issue if you import a server component from an
That said, sometimes barrel files can cause this type of issue if you import a server component from an
index.ts file that also exports client components.Scottish FoldOP
Can't provide the actual code since it is part of closed source org.
But here is the general structure
"use client"
import { useState, useEffect } from 'react';
function CampaignList() {
const [campaigns, setCampaigns] = useState([]);
useEffect(() => {
async function fetchCampaigns() {
const response = await fetch('/api/campaigns');
const data = await response.json();
setCampaigns(data);
}
fetchCampaigns();
}, []);
return (
<div>
{campaigns.map((campaign) => (
<div key={campaign.id}>
<h2>{campaign.title}</h2>
<p>{campaign.description}</p>
</div>
))}
</div>
);
}
export default CampaignList;
But here is the general structure
"use client"
import { useState, useEffect } from 'react';
function CampaignList() {
const [campaigns, setCampaigns] = useState([]);
useEffect(() => {
async function fetchCampaigns() {
const response = await fetch('/api/campaigns');
const data = await response.json();
setCampaigns(data);
}
fetchCampaigns();
}, []);
return (
<div>
{campaigns.map((campaign) => (
<div key={campaign.id}>
<h2>{campaign.title}</h2>
<p>{campaign.description}</p>
</div>
))}
</div>
);
}
export default CampaignList;
Hmmm... Since Next v13 making fetch requests to your own api endpoints is not the recommended way of getting data to your components. You can await a fetch call directly from a server component and pass down the list of campaigns.
But if for some reason you can't, or don't want to, try removing the async function and instead use the good old
But if for some reason you can't, or don't want to, try removing the async function and instead use the good old
fetch().then().catch() logic to update your state after fetching the data.No need for async/await
Just to check, but you didnt do
right? I have doen that mistake a bunch of times and you might have forgotten to add it here
export default async function CampaignList() right? I have doen that mistake a bunch of times and you might have forgotten to add it here
@not-milo.tsx Hmmm... Since Next v13 making fetch requests to your own api endpoints is not the recommended way of getting data to your components. You can await a fetch call directly from a server component and pass down the list of campaigns.
But if for some reason you can't, or don't want to, try removing the async function and instead use the good old `fetch().then().catch()` logic to update your state after fetching the data.
Scottish FoldOP
I want to fetch in the client component only, tried the promise version but getting the same issue.
@Arinji Just to check, but you didnt do
export default async function CampaignList()
right? I have doen that mistake a bunch of times and you might have forgotten to add it here
Scottish FoldOP
I checked it's just
export default CampaignList
export default CampaignList
weird, any other components which use async await? chec how you call them
Scottish FoldOP
I have made similar components before but never experienced this issue
cause if you make a client component call a component you made with async, but without the "use client" it becomes a client component
No, it doesn't
Scottish FoldOP
I error mostly comes when the user navigates using the browser's back or forward button
no no, its the opposite.. if you call a server component inside of a client component, the server component becomes client
@Arinji no no, its the opposite.. if you call a server component inside of a client component, the server component becomes client
Scottish FoldOP
Yeah that I am not doing
Scottish FoldOP
Ok
@Arinji no no, its the opposite.. if you call a server component inside of a client component, the server component becomes client
Nooo... First of all you can't import a server component from a client component. And second, if you pass a server component to a client components as child it still remains a server component. Think of it like wrapping a layout in a context provider. The layout's children remain server components even though they are wrapped by a client component (the provider).
@Scottish Fold I error mostly comes when the user navigates using the browser's back or forward button
Scottish FoldOP
Does this tell anything?
No, I don't see how navigating should affect your data fetching logic. At least not from the little code you shared.
Munchkin
Getting a bit confused by your code here.
Its should be
But i see you have a different way of exporting. Could you try doing it like i just did?
Its should be
export default function CampaignList()But i see you have a different way of exporting. Could you try doing it like i just did?
@Scottish Fold Can't provide the actual code since it is part of closed source org.
But here is the general structure
"use client"
import { useState, useEffect } from 'react';
function CampaignList() {
const [campaigns, setCampaigns] = useState([]);
useEffect(() => {
async function fetchCampaigns() {
const response = await fetch('/api/campaigns');
const data = await response.json();
setCampaigns(data);
}
fetchCampaigns();
}, []);
return (
<div>
{campaigns.map((campaign) => (
<div key={campaign.id}>
<h2>{campaign.title}</h2>
<p>{campaign.description}</p>
</div>
))}
</div>
);
}
export default CampaignList;
Silver Marten
i dont know why exactly you're getting this error but you can probably fix this by using server actions. just import your
fetchCampagins function from a different file as a server action// /actions.ts
"use server"
export async function fetchCampaigns() {
const response = await fetch('/api/campaigns');
const data = await response.json();
return data;
}import { fetchCampaigns } from "@lib/actions.ts"
export default function CampaignList() {
const [campaigns, setCampaigns] = useState([]);
useEffect(async () => {
// invoke the server action
const data = await fetchCampaigns();
setCampaigns(data);
}, []);
return (
<div>
{campaigns.map((campaign) => (
<div key={campaign.id}>
<h2>{campaign.title}</h2>
<p>{campaign.description}</p>
</div>
))}
</div>
);
}im not sure tho
Scottish FoldOP
Here's the error
@Silver Marten i dont know why exactly you're getting this error but you can *probably* fix this by using server actions. just import your `fetchCampagins` function from a different file as a server action
ts
// /actions.ts
"use server"
export async function fetchCampaigns() {
const response = await fetch('/api/campaigns');
const data = await response.json();
return data;
}
tsx
import { fetchCampaigns } from "@lib/actions.ts"
export default function CampaignList() {
const [campaigns, setCampaigns] = useState([]);
useEffect(async () => {
// invoke the server action
const data = await fetchCampaigns();
setCampaigns(data);
}, []);
return (
<div>
{campaigns.map((campaign) => (
<div key={campaign.id}>
<h2>{campaign.title}</h2>
<p>{campaign.description}</p>
</div>
))}
</div>
);
}
This would likely not make a difference. If the issue is with the async keyword, calling a different async function would not solve it.
@Munchkin Getting a bit confused by your code here.
Its should be `export default function CampaignList()`
But i see you have a different way of exporting. Could you try doing it like i just did?
How the component is exported is irrelevant and how he did it is equivalent to your suggestion. It's something much more subtle imo 

@Scottish Fold Can't provide the actual code since it is part of closed source org.
But here is the general structure
"use client"
import { useState, useEffect } from 'react';
function CampaignList() {
const [campaigns, setCampaigns] = useState([]);
useEffect(() => {
async function fetchCampaigns() {
const response = await fetch('/api/campaigns');
const data = await response.json();
setCampaigns(data);
}
fetchCampaigns();
}, []);
return (
<div>
{campaigns.map((campaign) => (
<div key={campaign.id}>
<h2>{campaign.title}</h2>
<p>{campaign.description}</p>
</div>
))}
</div>
);
}
export default CampaignList;
Can you make a minimum reproduction repo so we can test it out and see where's the problem?
@not-milo.tsx Can you make a minimum reproduction repo so we can test it out and see where's the problem?
Scottish FoldOP
I was not able to reproduce it in a separate repo, it's working fine there, but the same code here is causing the error
The error comes when the user moves to the campaign page using the browsers back or front keys
As a temporary solution I have added an event listener that would trigger a reload in that case.
It's not the ideal way but since the deadline for the project delivery is approaching, I am now working on other tickets
Thank you all for the efforts ðŸ™
Silver Marten
ohhhhh right my bad
@Bighead carp How can you use async in useEffect
Silver Marten
then is it possible to solve this by revalidating the data that's fetched from
/api/campaigns every x seconds and then just calling the fetchCampaigns() server action normally in the component like thisimport { fetchCampaigns } from "@lib/actions.ts"
export default function CampaignList() {
const campaigns = await fetchCampaigns();
return (
<div>
{campaigns.map((campaign) => (
<div key={campaign.id}>
<h2>{campaign.title}</h2>
<p>{campaign.description}</p>
</div>
))}
</div>
);
}Bighead carp
Is
CampaignList a server or client component@Scottish Fold Click to see attachment
Silver Marten
here it says its a client component but the one in the code i wrote is a server component
oh wait
you can't call server actions in a server component
Bighead carp
Right, then you can't export an async function as a client component
and you'll have to use useEffect or useMemo
Silver Marten
oh i see
thanks i understand it a bit more now
@Bighead carp Right, then you can't export an async function as a client component
Silver Marten
right so i was looking around and i figured that the solution for this type of problem would be to remove all the react hooks and just import the fetch function into a server component
but i also found that the same can be achieved by making
interface Props {
user: User
}
// Server component
export default async function TransactionList({ user }: Props) {
// Server action
const transactions: Transaction[] = await fetchAllTransactions(user);
return (
<div>
{transactions.map((transaction, index) => (
<TransactionCard key={index} transaction={transaction} />
))}
</div>
)
}export async function fetchAllTransactions(user: User) {
noStore()
const id = user.id?.toString();
try {
const res = await sql<Transaction>`
SELECT * FROM transactions
WHERE user_id=${id}
ORDER BY created_at DESC
`
const data = res.rows;
return data;
} catch (error) {
console.log("Database error", error);
throw new Error ("Failed to fetch all transactions.");
}
}but i also found that the same can be achieved by making
fetchAllTransactions a server action. and i was just wondering if theres anything that can be achieved by making this a server action?Bighead carp
Have you made sure you can't put the data into a server component with a suspense boundary?
Maybe thats better than fetching the data from the client side
Silver Marten
we're not fetching data from client side though
all of this code is run on the server
i think so at least im pretty new to this
Bighead carp
The title of this thread is async/await in client component
Silver Marten
oh i was just asking for my own clarification
my bad
Bighead carp
You dont need to make that
fetchAllTransactions function a server action if its being executed on the server sideSilver Marten
oh alr
Bighead carp
I would suggest reading up on it
Silver Marten
will do