Sitemap
devFemzy

devFemzy

Software Engineer

Day 5 — Client Components Done Right

5 min readDec 12, 2025

--

30 Days Excerpt from 6+ Years Experience

30 Days of Next.js

🌗 Context & Continuity

Previous Day: Server Components Mastery
Today’s Focus: Client Components Done Right
Coming Up Tomorrow: Hydration, Streaming & Suspense Boundaries

Yesterday, we dismantled one of the biggest mental shifts in modern Next.js: Server Components are the default, not the exception. We explored how rendering on the server changes performance, security, and architectural decisions.

Today builds directly on that foundation.

If Server Components are where your app should live, then Client Components are where interactivity earns its place. Understanding when, why, and how to use Client Components correctly is one of the clearest signals that separates junior engineers from senior ones in Next.js.

This is not about memorizing "use client".
This is about owning the boundary between logic and interactivity.

🧭 Introduction

A common mistake many developers make when learning App Router is swinging from one extreme to another:

  • First, everything becomes a Client Component because it “just works”.
  • Then, everything becomes a Server Component because it’s “the default”.

Senior engineers don’t live in extremes.

They understand tradeoffs, cost, and intent.

Today, we’ll demystify Client Components — not as a fallback, but as a precision tool. By the end of this article, you’ll understand:

  • What Client Components actually are
  • Why they exist in a Server Components world
  • How to design clean, performant boundaries
  • Why misuse silently degrades performance

This knowledge is foundational to becoming a confident Next.js engineer in production environments.

🧩 Core Concept Deep Dive

What Is a Client Component — Really?

A Client Component is a React component that:

  • Executes in the browser
  • Has access to browser-only APIs
  • Can use state, effects, and event handlers
  • Is bundled and shipped to the client

In Next.js App Router, Client Components opt into the traditional React runtime.

That opt-in is explicit.

When you write:

"use client"

You are telling Next.js:

“This file and everything it imports must run in the browser.”

This single directive triggers a cascade of consequences.

Why Client Components Exist at All

If Server Components are faster, safer, and cheaper — why not use them everywhere?

Because users interact with applications, not HTML.

Client Components are required for:

  • Click handlers
  • Form state
  • Modals and drawers
  • Animations
  • Browser APIs like localStorage
  • Effects tied to lifecycle
  • Real-time updates

In other words: interactivity lives on the client.

The mistake is not using Client Components.
The mistake is overusing them.

The Hidden Cost of "use client"

When a component becomes a Client Component:

  • Its JavaScript must be sent to the browser
  • Its dependencies become part of the client bundle
  • It participates in hydration
  • It increases memory usage
  • It affects time-to-interactive

Senior engineers treat "use client" like a performance budget decision, not a convenience switch.

🧠 Practical Breakdowns & Real-World Thinking

The Boundary Principle

A powerful mental model is this:

Keep Client Components as small and as close to the leaf nodes as possible.

Beginners often wrap entire pages in Client Components just to handle a button click.

Senior engineers ask a different question:

“What is the smallest possible surface area that truly needs to be interactive?”

The answer is rarely the whole page.

Composition Over Conversion

Instead of turning a page into a Client Component, experienced developers:

  • Keep the page and layout as Server Components
  • Extract only the interactive part
  • Pass data down as props
  • Let the client handle interaction only

This preserves all the benefits of server rendering while enabling rich UI behavior.

Common Junior Mistake

A frequent JJC pattern looks like this:

  • Needs a useState
  • Adds "use client" at the top
  • Imports everything into that file
  • Accidentally ships half the app to the browser

This works — but at a silent cost.

Get devFemzy’s stories in your inbox

Join Medium for free to get updates from this writer.

A senior engineer sees this as architectural leakage.

How Seniors Think Differently

Senior engineers ask:

  • Does this interaction truly require client state?
  • Can this be a server action instead?
  • Can I isolate the interactive concern?
  • What happens to bundle size if this grows?

Client Components are not avoided — they’re scoped.

🧠 Advanced Insights You Rarely Hear Early

Client Components Infect Downward

Once a file is marked as a Client Component:

  • All of its imports become client-side
  • You cannot import Server Components into it
  • You lose access to server-only features

This is why Client Components should usually sit at the edges, not the roots.

Client Components Are Not “Bad”

There’s a false narrative that Client Components are inferior.

That’s incorrect.

They are expensive, not wrong.

Used intentionally, they are essential for:

  • Design systems
  • Interaction layers
  • UI primitives
  • Controlled inputs
  • Visual transitions

The skill is knowing where they belong.

Architectural Best Practice

A healthy Next.js app often looks like this:

  • Server Components for data, layout, and structure
  • Client Components for:
  • Buttons
  • Forms
  • Toggles
  • Interactive widgets

This separation scales beautifully as teams grow.

🪜 Step-by-Step Understanding

Let’s walk through the thought process — not code.

  1. Start with a Server Component by default
  2. Identify what requires user interaction
  3. Extract that logic into a small Client Component
  4. Pass data down from the server
  5. Keep the client focused on behavior, not data fetching

This workflow leads to cleaner, faster, and more maintainable applications.

The key is intention.

⚠️ Common Pitfalls (And Why They Happen)

  • Turning entire pages into Client Components
    Happens because it feels easier. Fix it by isolating interaction.
  • Fetching data inside Client Components unnecessarily
    Happens due to old habits from CSR-only apps.
  • Overusing effects for things the server can handle
    Happens when lifecycle thinking replaces architecture thinking.
  • Ignoring bundle impact
    Happens because performance issues appear gradually, not immediately.

Each of these mistakes compounds as your app grows.

🧪 Mini-Reflection — What You Learned Today

Today unlocked a crucial mindset shift:

Client Components are not the default.
They are a deliberate opt-in for interactivity.

You now understand:

  • What "use client" really means
  • Why Client Components must be scoped carefully
  • How senior engineers design component boundaries
  • Why performance is architectural, not accidental

This is a major step toward writing production-grade Next.js.

🌉 Smooth Transition to Tomorrow

Today was about where interactivity lives.

Tomorrow, we’ll explore what happens when server-rendered HTML meets client-side JavaScript.

Hydration, streaming, and Suspense boundaries define:

  • How fast your app feels
  • How resilient it is under load
  • How users experience transitions

Understanding Client Components sets the stage perfectly for understanding hydration behavior and streaming architecture.

✨ Share Your Progress

If you’re following along, tweet your setup screenshot or your progress with:

#30DaysOfNextJS and tag me @devFemzy on Twitter, I’ll retweet some of your posts!

This is Day 3, Keep going!

See you tomorrow.

--

--