Lesson 11 +10 XP

Interleaving Server and Client Components

To build performant Next.js applications, you must know how to compose Server Components and Client Components together without breaking the RSC boundary.

Rule #1: You CANNOT import a Server Component into a Client Component

If a file marked with 'use client' directly imports a Server Component file, that component will be forcibly converted into a Client Component!


tsx
// ❌ WRONG PATTERN
'use client';

// HeavyServerList will be bundled for the client!
import HeavyServerList from './HeavyServerList';

export default function ClientContainer() {
  const [isOpen, setIsOpen] = useState(false);
  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen)}>Toggle</button>
      {isOpen && <HeavyServerList />}
    </div>
  );
}

Rule #2: Pass Server Components as children or Props

To render a Server Component inside a Client Component, pass the Server Component as a React node prop (such as children) from an overarching Server Component!


tsx
// ✅ CORRECT PATTERN - Client Component acts as a wrapper slot
// components/ClientModal.tsx
'use client';

import { useState } from 'react';

export default function ClientModal({ children }: { children: React.ReactNode }) {
  const [open, setOpen] = useState(true);

return (
    <div className="relative">
      <button onClick={() => setOpen(!open)}>Toggle Modal</button>
      {open && <div className="p-4 border shadow-lg">{children}</div>}
    </div>
  );
}
// app/page.tsx - Server Component composition root
import ClientModal from '@/components/ClientModal';
import HeavyServerList from '@/components/HeavyServerList';

export default async function Page() {
  return (
    <main>
      <h1>Dashboard Page</h1>
      {/* HeavyServerList remains a pure Server Component! */}
      <ClientModal>
        <HeavyServerList />
      </ClientModal>
    </main>
  );
}

Serialization Boundary Rules

When passing props from a Server Component to a Client Component, the prop values must be serializable across the network boundary.

Allowed Prop Types (Serializable)Disallowed Prop Types
Strings, Numbers, BooleansFunctions (onClick={() => ...})
Objects & Arrays (plain)Class Instances
null & undefinedSymbols & Unserializable closures
JSX Elements (via children slot)Complex Streams / File Handles

TL;DR

  • Never import a Server Component directly inside a 'use client' module.
  • Pass Server Components as children or JSX props to Client Components.
  • Data passed as props across the Server-to-Client boundary must be serializable JSON-like data.
  • Keep Client Components at the visual leaves of your component tree.