Introduction
Recently, React server components have received widespread attention and popularity. This is because the React server component allows developers to outsource component-related tasks to the server. This way, developers do not need to distribute bundled JavaScript and external API queries to hydrate components while avoiding situations that can increase latency on client applications. In this article, we will discuss what React server components are and how to integrate them into your build application.
What are server components?
Server components are new features introduced in React 18 and the default feature in 13. A server component is essentially a component type that retrieves data from a server and renders it on a server. This content is then streamed into the client application in a format that the client application can render.
Server components are rendered in a custom format, which does not have a standard protocol, but is similar to the JSON format. The reaction DOM recognizes this format and presents it appropriately after identification.
Problem statements introducing the concept of React server components
We will create a scenario to introduce the concept of server components. The product page can be structured as follows:
const ProductPage = ({ productId })=> { return ( <> <ProductDetails productId={productId}> <ProductItem productId={productId} /> <MatchedItems productId={ productId } /> <ProductDetails> </> ) }
Now we have many ways to obtain the data needed in the component, as shown below, obtain the data needed to obtain the component at one time:
const ProductPage = ({ productId })=> { const data = fetchContentsFromAPI(); return ( <> <ProductDetails details={} productId={productId}> <ProductItem item={} productId={productId} /> <MatchedItems items={} productId={productId} /> <ProductDetails> </> ) }
This method works well and has its advantages, such as:
- This approach is suitable for user experience, because all components are rendered on the client after getting the data.
However, it can also cause some problems, such as:
- Since it binds the data contents to the child components of the parent component, it creates a high degree of coupling. This makes these components difficult to maintain.
- This also goes against the concept of single responsibility, because child components are not responsible for their data alone and therefore rely on the data of the parent component.
- Loading time is long because it requires getting all data for all components at once.
To achieve single responsibility, we can reorganize the parent component to display the component as follows:
const ProductDetails = ({productId, children}) => { const details = fetchProductDetails(productId); return ( <> {{ children }} </> ) } const ProductItem = ({productId}) => { const item = fetchProductItem(productId); return (...) } const MatchedItems = ({productId}) => { const items = fetchMatchedItems(productId); return (...) } const ProductPage = ({ productId })=> { return ( <> <ProductDetails productId={productId}> <ProductItem productId={productId} /> <MatchedItems productId={productId} /> <ProductDetails> </> ) }
This method works well and has its advantages, such as:
- Single responsibility: Each component is responsible for its own data.
However, it can create some problems, such as:
- It may not be suitable for the user experience, as any child component may render on the client side based on the load time of its API call, allowing the user to see a part of the page before another component.
- In addition, since
ProductDetails
The component will precede the child component (ProductItem、MatchedItems
) rendering, so the order of data acquisition will cause network waterfall flow.
These methods have their pros and cons, but they have one common limitation. This limitation is that both methods require calling the API from the client to the server, which causes high latency between the client and the server.
It was this limitation that prompted the React team to introduce server components: components on the server. Because server components exist on the server, they can make API calls and render quickly than components rendered on the application client.
Although initially to address the limitations of high latency, new applications have emerged. Since components reside on the server, they can access the server infrastructure, which means they can connect to the database and query it.
The difference between React server components and client components
One of the main differences between server components and client components is that server components render components on the server, while client components render on the client.
Typically, for a client's React application, when a user requests a web page from the server, the server responds to the web page (Javascript file) to the browser. The browser downloads data (Javascript files) and uses it to build web pages. On the other hand, client components are sent to the client, thereby increasing the bundling size of the application (client components are typical traditional React components).
Another difference is their presentation environment, which gives them different properties, as explained below:
- Server components cannot use React hooks, such as useState, useReducer, useEffect, etc. This is because the server components are rendered on the server, so there is no access to hooks that can affect the DOM (Document Object Model), which only exists on the client. On the other hand, the client component is a normal React component that still has access to the hook.
- Server components cannot access browser APIs, such as SessionStorage, localStorage, etc. On the other hand, the client component is a normal React component that still has access to the browser API.
- Server components can use async/await for server-specific data sources such as databases, internal services, file systems, etc., while client components cannot directly access server-specific data sources.
The difference between React server components and React server-side rendering (SSR).
Server-side rendering (SSR) in React refers to the ability of an application to convert React components on the server into static HTML pages that are fully rendered to the client. React Server Components, on the other hand, collaborates with SSR through a mediation structure (similar to the JSON format protocol) to enable rendering without delivering any bundles to the client.
Server Component Case Study.
We will explain how to use server components in traditional React applications and applications.
Use server components in React applications. In a typical React application, the server component is like a normal React component.
Note that to use async/await in a typescript component with .tsx files, you need to upgrade the typescript version to 5.1.1. To learn more, visit here
Here is an example of a server component:
// Server Component const BlogPost = async({id, isEditing}) => { const post = await (id); return ( <div> <h1>{}</h1> <section>{}</section> </div> ); }
The client component looks like a normal React component, but added to the component fileuse client
Instructions. Technically speaking,use client
The directive declares the boundary between the server component and the client component.
// A client component 'use client' import React, { useState } from "react"; import { v4 as uuidv4 } from 'uuid'; const PostEditor = ({ blogPost }) => { const [post, setPost] = useState<any>({ id: uuidv4(), title: , content: , }) const onChange = (type: any, value: any)=> { switch(type){ case "title": setPost({...post, title: value}) break; case "content": setPost({...post, content: value}) break; default: break } } const submitPost = ()=> { // save blog post }; return ( <div> <div className="md:mx-auto px-6 md:px-0 mt-10 md:w-9/12"> <h1 className="my-4 text-center">Create Post</h1> <form onSubmit={submitPost}> <div className="mt-8"> <label className="text-white mb-2"> Title </label> <input type="text" placeholder="" value={} required onChange={(e)=> onChange("title", )} /> </div> <div className="mt-8"> <label className="text-white mb-2"> Add your Blog content </label> <textarea value={} required onChange={(e)=> onChange("content", )} ></textarea> </div> <div className="flex justify-end mt-8"> <button type="submit" className="px-4 py-4 bg-[#0e9f64] c-white border-radius" > Create Post </button> </div> </form> </div> </div> ); }; export default PostEditor;
There are some specific rules to know when using server and client components:
Server components cannot be imported into client components, but client components can be imported into server components. We will use the following example to illustrate how to import client components into server components:
// Server Component import db from 'db'; import NoteEditor from 'NoteEditor'; async function BlogPost({id, isEditing}) { const post = await (id); return ( <div> <h1>{}</h1> <section>{}</section> {isEditing ? <PostEditor blogPost={post} /> : null } </div> ); }
In the above code, we willPostEditor
(Client Component) The server component is imported.
When a client component is located within a server component, the server component can be passed to the client component as a child prop.
const ServerComponent1 = () => { return ( <ClientComponent> <ServerComponent2 /> </ClientComponent> ) }
Using server components in Next applications
By default, the server component is a normal React component created in the newly introduced App directory in Next 13.
// Server Component const BlogPost = async({id, isEditing}) => { const post = await (id); return ( <div> <h1>{}</h1> <section>{}</section> </div> ); }
Next 13
The client component in looks like a normal React component, but added in the component fileuse client
Instructions.
// A client component 'use client' import React, { useState } from "react"; import { v4 as uuidv4 } from 'uuid'; const PostEditor = ({ blogPost }) => { const [post, setPost] = useState<any>({ id: uuidv4(), title: , content: , }) const onChange = (type: any, value: any)=> { switch(type){ case "title": setPost({...post, title: value}) break; case "content": setPost({...post, content: value}) break; default: break } } const submitPost = ()=> { // save blog post }; return ( <div> <div className="md:mx-auto px-6 md:px-0 mt-10 md:w-9/12"> <h1 className="my-4 text-center">Create Post</h1> <form onSubmit={submitPost}> <div className="mt-8"> <label className="text-white mb-2"> Title </label> <input type="text" placeholder="" value={} required onChange={(e)=> onChange("title", )} /> </div> <div className="mt-8"> <label className="text-white mb-2"> Add your Blog content </label> <textarea value={} required onChange={(e)=> onChange("content", )} ></textarea> </div> <div className="flex justify-end mt-8"> <button type="submit" className="px-4 py-4 bg-[#0e9f64] c-white border-radius" > Create Post </button> </div> </form> </div> </div> ); }; export default PostEditor;
Pros and cons of React server components
We will cover the advantages and disadvantages of using server components in development.
advantage:
- Reduce bundles: Server components are "zero bundles" components because they do not increase the size of the Javascript bundle rendered by the client.
- Access server infrastructure: Using server components, you can seamlessly connect to databases, file systems and other server infrastructure.
- Because API calls can be delegated to server components running on the server, client latency is reduced.
shortcoming:
- The server component cannot access the client functionality.
- Since server components provide nearly the same advantages as regular SSR (server-side rendering) applications, and many people are used to using SSR, their adoption may not be fast.
- Because server components have access to the server infrastructure, it can lead to poor application design, as it may encourage developers to evade creating APIs or even standalone backends and instead perform queries and connect to databases directly through server components.
in conclusion
In this article, we introduce server components in React and discuss their uses and benefits. The React Server Components enable us to combine the advantages of client-side and server-side rendering components in a completely new way in React applications.
The above is a detailed explanation of how to use React server components. For more information about React server components, please pay attention to my other related articles!