Part 39: Enhancing Interactivity with Client Components in Next.js

[App] Client Components

Enhancing Interactivity with Client Components in Next.js

Welcome to our exploration of Client Components in Next.js, a framework that simplifies server-side rendering and static site generation for React applications. Until now, our pages have been static, with interactivity limited to navigating between pages. This navigation is managed automatically by Next.js, without requiring additional input from developers. Today, we’ll add a feature to make our pages more interactive and user-friendly—a "Share Link" button.

Many websites feature a "Share" button for users to easily share content. We will implement a similar feature by adding a button that allows users to copy the page URL to their clipboard.

To start, let's create a new component for this functionality. Inside the components directory, create a file named ShareLinkButton.jsx. We will export a function component from this file:

//'use client';
export default function ShareLinkButton() {
  const handleClick = () => {
    console.log('clicked!');
  };
  return (
    <button onClick={handleClick}
      className="border px-2 py-1 rounded text-slate-500 text-sm
                 hover:bg-orange-100 hover:text-slate-700">
      Share link
    </button>
  );
}

This component returns a simple button element with "Share link" as the text. The handleClick function logs a message to the console when the button is clicked.

Styling the Button

Our button could use some styling to make it more visually appealing. We’ll add some CSS classes to give it a border, padding, and rounded corners. We'll also set the text color to a neutral shade and make the font smaller. On hover, the button's background color will change to a darker orange, and the text will darken for contrast.

Integrating the Component

To integrate the ShareLinkButton into our page, we can import it and include it in our ReviewPage component. Here’s how you can add it after the date:

import Heading from '@/components/Heading';
import ShareLinkButton from '@/components/ShareLinkButton';
import { getReview, getSlugs } from '@/lib/reviews';

export default async function ReviewPage({ params: { slug } }) {
  const review = await getReview(slug);
  return (
    <>
      <Heading>{review.title}</Heading>
      <div className="flex gap-3 items-baseline">
        <p className="italic pb-2">{review.date}</p>
        <ShareLinkButton />
      </div>
      <p className="italic pb-2">{review.date}</p>
      <img src={review.image} alt={review.title} width="640" height="360" className="mb-2 rounded" />
      <article dangerouslySetInnerHTML={{ __html: review.body }} className="prose prose-slate max-w-screen-sm" />
    </>
  );
}

Aligning Elements

By wrapping the date and the ShareLinkButton in a div with flex styling, we place them on the same row. Adding items-baseline aligns the text properly.

Handling Interactivity with Client Components

When we try to add interactivity, such as logging a message on button click, we encounter an "Unhandled Runtime Error." This error suggests converting parts of the page to a Client Component for interactivity.

In Next.js, components are Server Components by default. To use client-side functionality, we need to convert these to Client Components. This involves understanding how Client Components work, which we will explore in an upcoming section.

Next Steps

To resolve the current issue and fully implement client-side interactivity, we need to understand Client Components further. In upcoming posts, we will delve deeper into this concept and demonstrate how to effectively use Client Components in Next.js.

Stay tuned for more insights on enhancing your Next.js applications with interactive features!

Last updated