Server Components
The source code of server components is not sent to the client, and their rendering process does not happen in the client. Only the result of the server-side rendering process is sent. It might be useful to think of Server Components as template generators that output static HTML, which is sent and displayed to the client. This isn't exactly what happens but it's close enough for a basic mental model.
Because of this, it is safe to make requests to sensitive APIs or resources within the code of Server Components themselves, as long as the output of their render process is carefully controlled.
React Server Components can be async
functions, which allows them to await promises.
{
"hello": "world"
}
{
"hello": "world"
}
Client Components
These are components that use browser-only APIs. They usually have some kind of interactivity or some kind of rendering that can only be done in the browser. They have the use client
directive at the top of their file.They behave like "traditional" react components most of the time.
In the RSC world, depending on the framework, Client Components can behave unexpectedly, especially during Hydration. We will look more closely at this later.
Shared Components
Shared Components can act as either Server or Client components. Because they don't use any APIs that are only available on the client or server, they can be rendered in either environment. They automatically "become" Server or Client components to match the environment they are imported into.
Typically, Shared Components are useful for things like UI elements that might need to be rendered on both the client and server.
Hi, I am a Shared component. I will be rendered on the server by default, but if a Client Component imports me, I will be rendered on the client.
To remain truly shareable, I should not use any client-only or server-only APIs. I will throw an error if I use an unsupported API in the wrong environment.
Hi, I am a Shared component. I will be rendered on the server by default, but if a Client Component imports me, I will be rendered on the client.
To remain truly shareable, I should not use any client-only or server-only APIs. I will throw an error if I use an unsupported API in the wrong environment.
It is up to you, the developer, to decide which components to use. The kind of component you use for a given task will vary, but it will determine a rendering strategy, how you fetch data, and how the user interacts with your app.
What do you need to do? | Server | Shared | Client |
---|---|---|---|
Fetch data | |||
Access backend resources (directly) | |||
Keep sensitive information on the server (access tokens, API keys, etc) | |||
Keep large dependencies on the server / Reduce client-side JavaScript | |||
Share common 'dumb' component code that can be rendered in browser and node.js | |||
Add interactivity and event listeners ( | |||
Use State and Lifecycle Effects ( | |||
Use browser-only APIs | |||
Use custom hooks that depend on state, effects, or browser-only APIs | |||
Handle edge cases where rendering on server is inefficient. |
As a rule of thumb, and as Next.js defaults dictate, Use Shared Components unless you need to use a Server Component feature like data fetching, and only use a Client Component when you need to use a browser-only API.
Of course, there are always exceptions, but the RSC paradigm provides you with maximum flexibility to tackle any problem.