Skip to the solution
MediumFrontend5 min read

How do you pass data from Server Components to Client Components in Next.js?

350 views

The problem

Question presented to candidate: "A server page loads a product and a Client Component needs it. How do you pass it, what can and cannot cross, and what do you do with a function you want to call on click?"

What a strong answer should cover:

  • Pass data as props; everything that crosses must be serializable by React.
  • Supported: primitives, plain objects and arrays, Date, Map, Set, BigInt, typed arrays, promises, JSX elements and Server Actions.
  • Rejected: plain functions, event handlers, class instances and objects with a null prototype.
  • A promise can be passed without awaiting and unwrapped in the client with use(), so the server can start streaming earlier.
  • Pass only what the client needs; every prop ends up in the page payload and is visible to the user.

Clarifying questions expected:

  • "Does the client need the whole record?" β€” send a slimmed object, not the database row.
  • "Must the page wait for this data?" β€” if not, pass the promise and wrap the client in Suspense.

Code / implementation expected: Yes β€” a server page passing a value, a promise and a Server Action.

  • nextjs
  • rsc
  • props
  • serialization

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

5 min read Β· 8 sections

Read the code

Passing a value, a promise and a Server Action
// app/product/[id]/page.tsx  (Server Component)
import { Suspense } from "react";
import { getProduct, getReviews } from "@/lib/data";
import { likeProduct } from "./actions";       // file starts with "use server"
import ProductCard from "./ProductCard";
import Reviews from "./Reviews";

export default async function Page({ params }: { params: Promise<{ id: string }> }) {
  const { id } = await params;
  const product = await getProduct(id);
  return (
    <>
      <ProductCard
        product={{ id: product.id, name: product.name, price: product.price }}
        onLike={likeProduct}
      />
      <Suspense fallback={<p>Loading reviews...</p>}>
        <Reviews reviewsPromise={getReviews(id)} />
      </Suspense>
    </>
  );
}

// app/product/[id]/Reviews.tsx
"use client";
import { use } from "react";
export default function Reviews({ reviewsPromise }: { reviewsPromise: Promise<{ id: string; text: string }[]> }) {
  const reviews = use(reviewsPromise);
  return <ul>{reviews.map((r) => <li key={r.id}>{r.text}</li>)}</ul>;
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 80 of 129 in Next.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Next.js questions
Up nextMedium

How do you debug Server Functions and hydration mismatches in Next.js 16.2?

Continue