With Next.js 13 and 14 making Server Components the default, it seemed like a game-changer—until developers started throwing "use client" onto every file like a quick fix.
But hold up—do you actually know when to use it?
Or are you just slapping it on every file out of fear, hoping it’ll magically fix hydration errors?
Sound Familiar?
🚨 "Why isn’t this component rendering?"
🚨 "Why can’t I use state here?"
🚨 "Whatever—just add "use client" and move on."
And just like that, you’ve completely missed the point of Server Components.
Let’s break it down properly:
1️⃣ When should you actually use "use client"?
2️⃣ When should you avoid it?
3️⃣ How can you structure your app the right way?
What Does "use client" Actually Do?
Before blaming "use client" for everything, let’s get clear on what it actually does.
By default, Next.js treats components as Server Components, meaning:
✅ They execute on the server.
✅ They don’t send unnecessary JavaScript to the browser.
✅ They can securely fetch data without exposing API calls.
But the moment you add "use client", everything changes:
❌ The component now becomes a Client Component.
❌ It loses access to server-side features like direct fetch().
❌ More JavaScript gets shipped to the browser, impacting performance.
When Should You Use "use client"?
Not every component needs to be a Client Component. But here’s when it actually makes sense:
✅ For components using state or hooks (useState
, useEffect
, useContext
, etc.)
"use client";
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)} className="p-2 bg-blue-500">
Count: {count}
</button>
);
}
Server Components Don't Have State—And They Never Will
Since Server Components never run in the browser, they can’t manage state.
So, if your component relies on useState or useEffect
, you have no choice—you must declare it as a Client Component.
Without "use client"
, trying to use useState
inside a Server Component will result in an error.
When Do You Actually Need "use client"?
✅ Event Handlers (onClick, onChange, onSubmit, etc.)
✅ Browser APIs (localStorage, window, document, etc.)
✅ Context Providers (React Context providers must be Client Components)
When Should You Avoid "use client"
?
🚨 If you don’t need it, don’t use it.
Here’s where many developers go wrong:
❌ Wrapping everything in a Client Component unnecessarily
// ❌ This is bad practice
"use client";
export default function StaticContent() {
return <h1 className="text-xl">This should have been a Server Component</h1>;
}
This component doesn’t need "use client" because it’s completely static.
Forcing it to run on the client only adds unnecessary JavaScript and slows things down.
❌ Fetching data on the client when it could be handled on the server
// ❌ Bad: Fetching data in a Client Component
"use client";
import { useState, useEffect } from "react";
export default function Users() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch("/api/users")
.then((res) => res.json())
.then((data) => setUsers(data));
}, []);
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
Better Approach:
Instead of fetching data on the client, fetch it on the server.
This keeps your app more efficient by reducing the amount of JavaScript sent to the client and leverages the power of Server Components.
✅ Good: Fetching Data in a Server Component
export default async function Users() {
const res = await fetch("https://jsonplaceholder.typicode.com/users");
const users = await res.json();
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
Why this is good:
Fetching the data on the server side helps avoid unnecessary JavaScript in the browser and ensures faster page load times.
By fetching data on the server, the data is loaded before the page is rendered, reducing the load on the client-side.
How to Properly Structure Your Components
Instead of blindly adding "use client" everywhere, a better approach is to split your components into:
✅ Server Components (use by default)
✅ Client Components (only when absolutely necessary)
This ensures optimal performance and avoids unnecessary complexity in your app.
// Server Component
import Counter from "./Counter";
export default function Page() {
return (
<div>
<h1 className="text-xl">Hello, Next.js</h1>
<Counter />
</div>
);
}
// Client Component (Counter.tsx)
"use client";
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}
Why is This Better?
The Page component stays as a Server Component (optimized, no extra JavaScript).
The Counter component is a Client Component (since it needs state).
🔹 Don’t use "use client"
unless your component needs state, effects, or event handlers.
🔹 Keep most of your app server-rendered for better performance.
🔹 Use "use client"
only when necessary and structure Client Components properly.
I hope this was helpful, and I’d be happy to connect and follow each other!