Client components in Next.js¶
Understanding Client Components ('use client')¶
Next.js App Router applications primarily render components on the server by default (these are Server Components). This is great for performance, SEO, and security. However, many parts of a web application need interactivity, browser APIs, or state management that can only happen on the client-side. This is where Client Components come in.
What is a Client Component?¶
A Client Component is a React component that is rendered on the client-side (in the user's browser). While they might initially be rendered on the server for the first page load (a process called hydration), their primary purpose is to enable interactivity, manage state, and access browser-specific APIs (like window or localStorage).
When and Why to Use 'use client'¶
You should mark a component as a Client Component using the 'use client' directive at the very top of the file when it needs:
- Interactivity: Handling user interactions like clicks, input changes, hover effects.
- State Management: Using React Hooks like
useStateoruseReducer. - Lifecycle Effects: Using
useEffectto perform side effects that run in the browser. - Browser-specific APIs: Accessing
window,document,localStorage, etc. - Custom Hooks: If a custom hook uses
useStateoruseEffect, any component using that hook must be a Client Component.
The 'use client' directive acts as a "boundary" between Server Components and Client Components. All modules imported into a Client Component are considered Client Components themselves, or can be Server Components that are then "passed" into the Client Component as props.
How to Mark a Component as a Client Component¶
To mark a component as a Client Component, simply add the string 'use client'; at the very top of the file, before any imports.
Let's demonstrate this by creating a simple interactive counter component.
-
Create a new file for our counter component:
components/Counter.tsxmy-task-app/ └── components/ ├── Header.tsx ├── Footer.tsx ├── Counter.tsx <-- NEW FILEcomponents/Counter.tsx// components/Counter.tsx // This is a Client Component that demonstrates basic interactivity and state management. 'use client'; // This directive marks the component as a Client Component. import { useState } from 'react'; // Import the useState hook export default function Counter() { // Use the useState hook to manage the 'count' state. // `count` holds the current value, `setCount` is a function to update it. const [count, setCount] = useState(0); // Event handler for incrementing the count const increment = () => { setCount(count + 1); }; // Event handler for decrementing the count const decrement = () => { setCount(count - 1); }; return ( <div className="flex flex-col items-center p-6 bg-white rounded-lg shadow-md border border-gray-200"> <h3 className="text-2xl font-bold text-gray-800 mb-4">Interactive Counter</h3> <p className="text-5xl font-extrabold text-blue-600 mb-6">{count}</p> <div className="flex space-x-4"> <button onClick={decrement} className="px-6 py-3 bg-red-500 text-white rounded-lg shadow-md hover:bg-red-600 transition duration-300 transform hover:scale-105" > Decrement </button> <button onClick={increment} className="px-6 py-3 bg-green-500 text-white rounded-lg shadow-md hover:bg-green-600 transition duration-300 transform hover:scale-105" > Increment </button> </div> </div> ); } -
Integrate
Counter.tsxintoapp/page.tsx: Now, let's place our newCountercomponent on the homepage to see it in action.app/page.tsx(Update this file)
// app/page.tsx
// This file defines the content for the homepage ('/') of the application.
// Updated to include the Counter Client Component.
import Counter from '../components/Counter'; // Import the Counter component
export default function HomePage() {
return (
<div className="flex flex-col items-center justify-center min-h-[calc(100vh-250px)] text-center px-4 py-8 space-y-8">
<h2 className="text-4xl md:text-5xl font-bold text-blue-700 mb-4 animate-fade-in">
Welcome to My TaskFlow!
</h2>
<p className="text-xl text-gray-600 mb-8 max-w-2xl animate-slide-up">
Your simple solution for organizing tasks and boosting productivity.
</p>
<p className="text-md text-gray-500">
Get started by logging in or signing up to manage your daily tasks with ease.
</p>
{/* Add the Counter component here to demonstrate Client Components */}
<Counter />
</div>
);
}
Summary¶
What we've done:
- We've created a
Counter.tsxcomponent and explicitly marked it as a Client Component with'use client'. - We've used the
useStatehook to manage its internalcountstate. - We've integrated this Client Component into our
HomePage(which is a Server Component). This demonstrates that Server Components can import and use Client Components.
To see the Client Component in action:
- Ensure your development server is running (
npm run dev). - Open
http://localhost:3000. - Interact with the "Increment" and "Decrement" buttons on the counter. You'll see the count update dynamically on the page, demonstrating client-side interactivity.