As we continue to explore the world of React Server Components (RSC), one powerful technique has emerged that allows us to compose our server-side rendered UI in a more declarative and reusable way: React Server Component Composition.
In this article, we'll delve into the world of RSC composition, exploring how to pass server components as children or props to client components. We'll see concrete examples, discuss when not to use this technique, and highlight related Apiary lessons that can help you master this powerful tool.
The Technique
React Server Component Composition is built on top of the existing startTransition API provided by React. When using RSC composition, we're essentially creating a new component tree that's composed of server-side rendered components as children or props to client-side components.
Here's a simplified example to illustrate this concept:
import type { ComponentProps } from 'react';
import { startTransition, useSyncExternalStore } from 'react';
const ServerHeader = () => {
// Server-side logic here...
};
const ClientFooter = (props: ComponentProps<typeof ServerHeader>) => {
const serverContent = props.children;
return (
<footer>
{/* Client-side logic here... */}
{serverContent}
</footer>
);
};
In this example, we define a ServerHeader component that's rendered on the server. We then pass it as a child to the ClientFooter component, which is rendered on the client.
Concrete Examples
Let's explore two more concrete examples to demonstrate RSC composition in action:
Example 1: Passing Server Components as Children
const ServerHero = () => {
// Server-side logic here...
};
const ClientPage = (props: { children?: React.ReactNode }) => {
const serverContent = props.children;
return (
<main>
{/* Client-side logic here... */}
{serverContent}
</main>
);
};
In this example, we define a ServerHero component that's rendered on the server. We then pass it as a child to the ClientPage component, which is rendered on the client.
Example 2: Passing Server Components as Props
const ServerSearchForm = () => {
// Server-side logic here...
};
const ClientHeader = (props: { searchForm?: React.ReactNode }) => {
const serverContent = props.searchForm;
return (
<header>
{/* Client-side logic here... */}
{serverContent}
</header>
);
};
In this example, we define a ServerSearchForm component that's rendered on the server. We then pass it as a prop to the ClientHeader component, which is rendered on the client.
When Not to Use It
While RSC composition is a powerful tool, there are cases where it might not be the best choice:
- Complex rendering logic: If your server-side rendering logic is complex or requires significant computations, it's better to keep it on the server and avoid passing it as children or props.
- Large data sets: Passing large data sets from the server to the client can lead to performance issues. In such cases, consider using a more efficient data synchronization mechanism.
Related Apiary Lessons
To help you master RSC composition, be sure to check out these related Apiary lessons:
Conclusion
React Server Component Composition is a powerful technique that allows us to compose our server-side rendered UI in a more declarative and reusable way. By passing server components as children or props to client components, we can create complex UI compositions while maintaining the benefits of server-side rendering.
As you continue on your journey with RSC composition, remember to consider the trade-offs and optimize for performance whenever possible. Happy building!
"A hive mind is a beautiful thing, but only when composed of individual bees working together in harmony."