f in x
Server Components vs Client Components in Next.js: When to Use Which and Why
> cd .. / HUB_EDITORIALE
Analisi dei dati e metriche

Server Components vs Client Components in Next.js: When to Use Which and Why

[2026-06-05] Author: Ing. Calogero Bono

Your Next.js app works, but you are not sure if a component should be server or client? You have already run into the error of importing a hook into a component that doesn't support it? Time to clear things up. We at Meteora Web work with Next.js on real projects — proprietary platforms, e-commerce, dashboards. The choice between Server and Client Components is not a technical detail: it's the difference between an app that flies and one that struggles.

Why Two Types of Components?

React Server Components (RSC) are not a trend. They come from a concrete need: reduce the JavaScript sent to the browser. Before RSC, every React component executed on the client. Even if it only printed static HTML, the browser had to download, parse, and run all that component's code. With RSC, server components run once on the server. The result is pure HTML, zero KB of JavaScript.

Client Components still run in the browser. They are needed for anything that requires interactivity: clicks, inputs, animations, side effects. But not every component needs that.

A Concrete Example

Imagine an e-commerce product page: header, description, price, an "Add to Cart" button. Description and price are static: they can be Server Components. The button with cart state must be a Client Component. Result: less JS, faster page. Simple, right? Yet we still see too many projects marking everything as 'use client' for convenience. They pay in performance.

When to Use Server Components

A component should be server if it does not need browser interactivity. Specifically:

  • Data display: fetch data from DB or API, render lists, tables, static content.
  • Structural layout: header, footer, sidebar, grids that don't change state.
  • Components accessing sensitive resources (tokens, API keys): server can access env vars or DB without exposing them to client.
  • Any component not using React hooks (useState, useEffect, useReducer, useContext) or browser events (onClick, onChange).

Concrete Benefits of Server Components

  • 0 JavaScript bundle: component not included in client bundle.
  • Direct backend access: you can query the DB without intermediary APIs.
  • Security: sensitive logic (pricing, discounts) never reaches client.
  • Better SEO: HTML already rendered, Google sees it immediately.
// Server Component (default)
export default async function ProductList() {
  const products = await db.query('SELECT * FROM products');
  return (
    
    {products.map(p => (
  • {p.name} - €{p.price}
  • ))}
); }

No 'use client', no client-side fetch. Fast, secure, simple.

When to Use Client Components

A component must be client if it needs interactivity or browser APIs. Classic cases:

  • User events: onClick, onChange, onSubmit, onScroll.
  • State and effect hooks: useState, useEffect, useReducer, useCallback.
  • Context and providers: if using React Context (theme, auth), the provider must be client.
  • Browser APIs: localStorage, navigator, window, document.
  • Third-party components: many widgets, sliders, maps, text editors require client.

How to Declare a Client Component

Simply add 'use client' at the top of the file, before any imports.

'use client';

import { useState } from 'react';

export default function AddToCartButton({ productId }: { productId: number }) {
  const [loading, setLoading] = useState(false);

  const handleClick = async () => {
    setLoading(true);
    await fetch('/api/cart/add', { method: 'POST', body: JSON.stringify({ productId }) });
    setLoading(false);
  };

  return (
    
  );
}

Client Inheritance

If you import a Client Component inside a Server Component, that import point becomes the boundary. The Server Component can contain a Client Component, but cannot pass functions or non-serializable objects (except simple props). Next.js will warn you if you try to pass a callback directly to a Client Component — you will need Server Actions or just data.

The Practical Rule: Start from the Need

Do not start by asking "is this component server or client?". Start by asking: does it need interactivity?

  • No → Server Component. Done.
  • Yes → Client Component. But only that one. Try to keep interactive logic in small, focused components, and everything else (layout, data, static markup) out of the client.

We at Meteora Web apply this rule on every project. A typical beginner mistake is putting 'use client' on an entire page. That pulls all page JavaScript into the bundle. Much better to have a Server Component for the page and nest only interactive components as Client.

Example of Correct Composition

// page.tsx (Server Component)
import ProductList from './ProductList';
import AddToCartButton from './AddToCartButton';

export default async function ProductPage() {
  const products = await getProducts();
  return (
    <>
      
      {/* AddToCartButton is Client, but we import it here */}
      
    
  );
}

// ProductList.tsx (Server Component - no 'use client')
export default function ProductList({ products }) {
  return products.map(p => 
{p.name}
); } // AddToCartButton.tsx (Client Component) 'use client'; // ...

Edge Cases & Borderline Situations

Components That Seem Server But Use Context

If a component needs to read Context (e.g., theme, language), it cannot be server because Context is available only on client. You will have to make it client or pass data via props from server.

Hybrid Data Fetching

You can do server-side fetching with async in a Server Component, but if you need mutations (e.g., forms) without page reload, use Server Actions. Server Actions are server-side functions callable from Client Components. That keeps server logic without exposing it.

'use client';
import { addToCart } from './actions';

export default function AddToCart({ productId }) {
  return (
    
); }

The addToCart function (Server Action) runs on the server without exposing sensitive logic in the bundle.

Third-Party Components

Many UI libraries (e.g., Shadcn/ui, MUI, Chakra) require client. Check their docs: if they use 'use client' internally, you cannot import them directly in a Server Component without wrapping them in a Client Component wrapper.

Performance Metrics to Watch

  • Bundle size: use tools like next/bundle-analyzer to see how much JS you are sending.
  • Loading waterfall: Server Components reduce first rendering time (better TTFB).
  • Interactivity: First Input Delay (FID) improves with less client JS.

In Summary — What to Do Now

  1. Check every file: if it has no hooks or events, remove 'use client'. Start with presentation components.
  2. Move data fetching: from client to server. Use async in Server Components.
  3. Isolate interactivity: create small, focused components only for the interactive part, leave the rest server.
  4. Verify dependencies: if you import a library, check if it is client-only. If so, create a wrapper.
  5. Use Server Actions for forms: avoid unnecessary API routes, keep server logic secure.

For deeper reading, check the official Next.js documentation on Server Components: React Server Components.

Sponsored Protocol

Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Co-founder di Meteora Web. Ingegnere informatico, sviluppo ecosistemi digitali ad alte prestazioni. AI, automazione, SEO tecnica e infrastrutture web. Scrivo di tecnologia per rendere complesso… semplice.

[ Read Full Dossier ]

Hai bisogno di applicare questa strategia?

Esegui il protocollo di contatto per iniziare un progetto con noi.

> INIZIA_PROGETTO

Sponsored

> MW_JOURNAL

> READ_ALL()