Decoding the Hype: What Are React Server Components?
The announcement of React Server Components was a paradigm shift in the world of React. But what exactly is a React Server Component?
And is it something you should use in your application? Does it replace SSR and suspense? Let’s go through each of these questions individually and better understand the core concepts behind React Server Components, their advantages, and their impact on modern web development practices.
Before we go any further, I would like to make it clear that at the time of writing this post, React Server Components are an experimental feature and are not fully production-ready yet.
Alright, let’s get into it! As the name suggests, React Server Components (RSCs) are React components that run on the server. These components run exclusively on the server and are never shipped to the client.
Simply put, Imagine you're building a complex React application. The challenge is handling large amounts of data and ensuring a snappy user experience. This is where React Server Components come into play.
In a typical React setup, all the heavy lifting, including rendering components and fetching data, happens on the client side. React Server Components, however, bring a fresh approach by enabling you to distribute some of this workload to the server. Let’s take a look at an example:
async function Pokemon(props) {
const { id } = props;
const pokemon = await fetch(`https://pokeapi.co/api/v2/ability/${id}`);
return (
<div>
<h1>{pokemon.name}</h1>
/* Other Pokémon data */
</div>
);
}
Here, we fetch data for an API and pre-render it on the server. React then seamlessly streams the content to the client side, where it is hydrated.
In essence, React Server Components offer a powerful way to balance the workload between the server and the client, resulting in a faster, more efficient, and scalable React application. They shine in scenarios where optimizing for performance, especially in terms of rendering and data fetching, is a top priority.
Now that we know what a React Server Component is, there are some key features that you should be aware of as well:
- Zero Bundle Size. Server Components do not add to the client-side bundle size. They are rendered on the server and send minimal, serialized UI to the client. Want to use a library but worried about the increase in the bundle size? With server components, you can avoid sending this to the client, resulting in no increase in the JavaScript bundle size.
- Rich Data Fetching. They can directly access server-side data sources, eliminating the need for additional data-fetching layers on the client side.
- Unified Development Model. Developers can seamlessly intermix client and server components, streamlining the development process.
- No re-renders. RSCs do not re-render. They run once to generate the UI, and that’s it. As server components only run on the server, they do not reach the client at all. This is why you can not use state or effects with these components.
- One of the cooler things about Server Components is the client state retention. When you make a change to a server component, such as manipulating data via it, the refetching of the tree does not cause the existing client state to reset. This results in a smoother user experience.
⚠️ Please note that re-rendering does happen when a user navigates around or reloads the page.
Let’s take a look at how exactly a Server Component is rendered.
- Request Handling. The server determines which components are needed upon a user's request.
- Server-side Execution. Server Components execute on the server, accessing databases or file systems if necessary.
- Serialization. The output is serialized and sent to the client.
- Hydration. The client (browser) then receives the serialized data and starts the work of constructing the React tree that will be rendered.
We have been talking about server components a lot, but what are client components? Well, those are just our good ol’ React components that have been renamed. This is done to make distinguishing between server and client components easier.
While server components focus on server-side magic and clever revalidation, client components do the heavy lifting on the user's device. They handle dynamic interactions and manage the local state.
The " use client " directive explicitly designates a component as a client component. By placing this directive at the top of a file, you signal to the bundler that the associated component is intended for execution on the client side.
"use client"
import React from 'react';
function EditPokemonName() {
const [name, setName] = useState("");
const handleNameChange = (newName) => {
//code
};
return (
<div>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<button onClick={() => handleNameChange(name)}>
Update Pokémon Name
</button>
</div>
);
}
export default EditPokemon;
The component above is a client component, you can absolutely add client components in server components. Below, we add the EditPokemonName component to our server component.
async function Pokemon(props) {
const { id } = props;
const pokemon = await fetch(`https://pokeapi.co/api/v2/ability/${id}`);
return (
<div>
<h1>{pokemon.name}</h1>
<EditPokemonName/>
</div>
);
}
In conclusion, these two work as a team, resulting in a more seamless experience for the end user. One thing to note here is that you cannot next a server component in a client component. This might be a little confusing and take some time getting used to.
So, do RSCs replace SSR? No, they do not. We continue to depend on server-side rendering (SSR) to generate the initial HTML. React Server Components extends this capability by allowing the exclusion of specific components from the client-side JavaScript bundle, ensuring their execution solely on the server.
Interestingly, React Server Components can be utilized even without server-side rendering. However, in practice, employing them together yields superior results. As the React team has mentioned, these two complement each other. You can use the server component without using SSR and vice-versa.
To make the adoption more convenient, server components will initially be adopted via meta—frameworks such as Next.js. Currently, Next.js is the only framework that utilizes these. You can keep track of the frameworks in the React documentation.
Wondering where to go from here? Here are a few resources that would be helpful:
React Server Components represent a significant leap in web development, offering a more efficient, performance-oriented approach to building web applications. As this technology evolves, it's poised to redefine modern web development's best practices and standards, emphasizing performance, simplicity, and a seamless developer experience.