Getting the client component async error: how to rewrite this Next.js client component with useEffect?

Summary

The error message “page is an async Client Component. Only Server Components can be async” occurs when trying to use async functionality in a client component. This is a common issue in Next.js applications, especially when using Sanity CMS. The problem arises from the fact that client components cannot be async, whereas server components can.

Root Cause

The root cause of this issue is the use of async functionality in a client component. Specifically, the page function is defined as async, which is not allowed in client components. The reasons for this include:

  • Client components are rendered on the client-side, and async functionality can cause issues with rendering.
  • Server components are rendered on the server-side, and async functionality is allowed because it can be handled by the server.

Why This Happens in Real Systems

This issue occurs in real systems because of the way Next.js handles client and server components. When using useParams from next/navigation, it is not possible to make the page component a server component. This is because useParams is a client-side hook, and it cannot be used in server components. The consequences of this include:

  • Async functionality cannot be used in client components.
  • UseParams cannot be used in server components.

Real-World Impact

The real-world impact of this issue is that it can cause errors and prevent the application from rendering correctly. The effects of this include:

  • Error messages will be displayed to the user.
  • Application functionality will be impaired.
  • User experience will be negatively impacted.

Example or Code

import { useEffect, useState } from 'react';
import { useParams } from 'next/navigation';
import { client } from '@/sanity/lib/client';
import { groq } from 'next-sanity';

const Page = () => {
  const { slug } = useParams();
  const [product, setProduct] = useState(null);

  useEffect(() => {
    const fetchProduct = async () => {
      const products = await client.fetch(groq`*[_type=="product"]`);
      const product = products.find((product) => product.slug.current == slug);
      setProduct(product);
    };
    fetchProduct();
  }, [slug]);

  return (
    
      {product && (
        
          
          
        
  );
};

export default Page;

How Senior Engineers Fix It

Senior engineers fix this issue by using useEffect to handle the async functionality, as shown in the example code. This allows the client component to handle the async functionality without causing errors. The key takeaways are:

  • UseEffect can be used to handle async functionality in client components.
  • UseParams can be used in client components.

Why Juniors Miss It

Juniors may miss this solution because they are not familiar with the useEffect hook or the limitations of client components in Next.js. The reasons for this include:

  • Lack of experience with Next.js and React.
  • Limited understanding of async functionality and client components.
  • Insufficient knowledge of useEffect and its use cases.