Server-to-Client Component Props
In React Server Components, values passed from a Server Component into a Client Component must be supported by React's server-to-client serialization protocol. Understanding this boundary helps frontend engineers design component APIs, avoid serialization errors, and keep server-only logic out of browser bundles.
React Server Components allow parts of a React application to execute on the server while Client Components provide browser-side interactivity. A Server Component can render a Client Component and supply its initial props. React transfers the necessary information through its Server Components payload, which is different from simply converting every prop into JSON.
Props crossing this boundary must use types supported by React's serialization protocol. These include primitives, arrays, plain objects, and certain built-in types such as Date, Map, and Set. React also supports some special values, including references to Server Functions. Ordinary functions and arbitrary class instances cannot generally cross the boundary as props.
The distinction matters because a Server Component executes in a different environment from its Client Component descendants. Server-only resources, such as database connections, filesystem handles, and private service credentials, should remain on the server. Instead, the server can extract the information needed by the interface and pass an appropriate serializable representation to the client.
Client Components are identified by the `use client` directive at their module boundary. A Server Component can import and render an exported Client Component, passing supported props into it. Components imported by that client entry point become part of its client module graph, so placing the directive unnecessarily high in the component tree can increase the amount of JavaScript delivered to the browser.
When a Client Component needs to initiate server-side work, a Server Function can provide an explicitly supported server-call mechanism. A function defined in an ordinary Server Component is not automatically transferable merely because it is passed as a prop. In practice, keep data transformation and privileged operations on the server, send only the information the client requires, and use supported server-call mechanisms for operations that must execute remotely.
Key points
- Server-to-client props must be representable by React's Server Components transport.
- React's supported values extend beyond JSON and include Date, Map, Set, and certain other built-in types.
- Ordinary functions, arbitrary class instances, and server-only resources are unsuitable as props across the boundary.
- Server Functions are a special supported mechanism for invoking server-side operations from client code.
- The `use client` directive establishes a client module boundary rather than marking every component that renders in a browser.
- Prefer small, purpose-built data objects over transferring unnecessary server-side data.
Interview questions
What kinds of props can a Server Component pass to a Client Component?
The props must use values supported by React's Server Components serialization protocol. Common examples include strings, numbers, booleans, null, arrays, and plain objects containing supported values. React also supports additional types, including Date, Map, and Set, as well as certain special references. Ordinary callback functions and arbitrary class instances generally cannot cross this boundary. A practical approach is to define a small data type containing exactly the information the Client Component needs.
Why can't you pass an ordinary event handler from a Server Component into a Client Component?
An ordinary JavaScript function depends on its execution environment and may capture variables that exist only in server memory. React cannot generally transfer that executable closure through the Server Components payload. Browser event handlers should normally be defined inside a Client Component or another module in the client graph. If an interaction requires server-side execution, an explicitly designated Server Function may be passed through React's supported mechanism. This distinction separates local browser behavior from remote server operations.
How would you pass data returned by an ORM from a Server Component to a Client Component?
I would first identify which fields the Client Component actually requires. Rather than pass an ORM model instance directly, I would construct a plain data object containing those fields and ensure its values are supported by React's transport. I would also remove credentials, internal identifiers that should remain private, and other unnecessary sensitive information. Supported values such as Date can be preserved when appropriate, although converting dates to strings may be useful when defining a framework-independent API. This creates a deliberate contract between the server's persistence model and the client interface.
What does the use client directive change about prop serialization?
The `use client` directive identifies a module as a client entry point. When a Server Component renders an exported component from that module, the props supplied across the boundary must be serializable using React's supported protocol. The directive also establishes a client dependency graph containing modules imported by that entry point. It does not mean that every prop passed between components inside that graph must be serialized. For example, a parent Client Component can pass a normal event callback to a child Client Component without crossing the server-client boundary.
How would you design a server-rendered product page that includes an interactive purchase button?
I would keep product retrieval and other server-only operations in a Server Component or an appropriate server-side data layer. The interactive purchase control would be a Client Component receiving a minimal set of supported props, such as the product identifier, display name, and price representation. Browser interactions, including local loading state, would remain in client code. A purchase request could invoke a properly authorized Server Function or an API endpoint, depending on the application architecture. The server must independently validate the product, current price, user permissions, and requested operation rather than trusting values supplied by the browser.
How would you investigate a serialization error at a Server Component boundary in a large React application?
I would locate the Server Component rendering the affected client entry point and inspect the props passed across that boundary. I would examine nested values for ordinary functions, custom class instances, or other unsupported objects, paying particular attention to values returned by external libraries. I would reduce the problematic prop to a minimal example and replace incompatible values with explicit supported representations. If the application needs server-side behavior, I would determine whether a Server Function or a separate API request is appropriate. Finally, I would add a focused regression test and review the component contract to prevent the same category of error from recurring.