Building an infinite scroll in next.js, I am trying to call my serverAction to loadMoreData and using async/await with it to wait for the API call and get result.
Getting an error:
"async/await is not yet supported in Client Components, only Server Components."
page.tsx is a server component and calls the same server action one time for initial images.
// page.tsx
const Home = async ({ searchParams }) => {
const searchKeyword =
typeof searchParams.keyword === "string" ? searchParams.keyword : "";
let apiResponse = await getPhotos({ query: searchKeyword });
return (
<main className='p-6 flex justify-center w-full min-h-screen bg-black'>
<InfiniteScrollData
search={searchKeyword}
initialData={apiResponse?.results || []}
/>
</main>
);
};
export default Home;
Here is the server action:
// actions.ts
"use server";
export const getData = async ({
query,
}) => {
const { response } = await fetchData({
query,
});
apiResponse = response;
return response;
};
And following is the client component
// InfiniteScrollData.tsx
"use client";
// imports
const InfiniteScrollImages: = ({
search,
initialData,
}) => {
const [data, setData] = useState(initialData);
const [page, setPage] = useState(1);
const [loaderRef, inView] = useInView();
const loadMoreData = useCallback(async () => {
const next = page + 1;
const response = await getData({ query: search, page: next });
if (response?.results?.length) {
setPage(next);
setData((prev) => [...prev, ...(response?.results || [])]);
}
}, [page, search]);
useEffect(() => {
if (inView) {
loadMoreData();
}
}, [inView, loadMoreData]);
return (
<>
<div>
{photos?.map((item) => (
<Card key={item.id} data={item} />
))}
</div>
<div ref={loaderRef}>
<Loader />
</div>
</>
);
};
export default InfiniteScrollImages;
Using [email protected]
Maybe there is another way of calling server actions from client components?
2
Answers
Your error directly says that you cannot do
await
functions in client components, so you should find away to get rid of that in your code:As the error suggested async await isn’t supported in client components.
Your alternative would be to handle promises. Your getData async function returns a promise which you can handle in your useCallback or just return the promise there as well and handle the promise in the useEffect
Without a demo I am kind of guessing so here is a rough solution:
On Nextjs documentation for client data fetching this is the example they give: