Skip to content

Commit 3ac9684

Browse files
Add Server Components Article
1 parent 20b055e commit 3ac9684

File tree

1 file changed

+236
-0
lines changed
  • src/pages/2023-11/react-server-components

1 file changed

+236
-0
lines changed
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
---
2+
layout: "@layouts/BlogPost.astro"
3+
title: "React Server Components - A New Paradigm"
4+
date: "2023-11-27"
5+
description: "Server components are the new way of writing React applications and it changes everything about React making it easier than ever to create complex applications. This article goes in depth into everything you need to know about server components."
6+
tags: ["React"]
7+
---
8+
9+
import Tangent from "@blogComponents/lib/Tangent.astro"
10+
11+
It has been quite a few years since React released hooks and over that time opinions have changed from super excited to extremley frustrated. Developers are becoming more and more frustrated with React hooks and that is almost entirely due to fetching data and more specifically the `useEffect` hook.
12+
13+
Before React fetching data was a simple process you did on the server before rendering your pages, but with React pushing everything to the client this data fetching became infinitely more complex since you now had additional error and loading states to deal with. This is where server components come in. Server components are a new way of writing React applications and drastically simplifies the painful process of fetching data while retaining all the benefits of React.
14+
15+
## What Are Server Components?
16+
17+
The big thing that makes server component different than client components is that server components never render on the client and instead only render on the server. This may sound like a downside since these components are less flexible, but since these components never touch the client it makes data fetching a breeze. Here is a comparison of a client component and a server component.
18+
19+
```jsx
20+
function ClientComponent() {
21+
const [data, setData] = useState(null)
22+
const [loading, setLoading] = useState(true)
23+
const [errr, setError] = useState(false)
24+
25+
useEffect(() => {
26+
setLoading(true)
27+
setData(undefined)
28+
setError(false)
29+
30+
const controller = new AbortController()
31+
32+
fetch("/api/data", { signal: controller.signal })
33+
.then(res => res.json())
34+
.then(data => setData(data))
35+
.catch(error => setError(true))
36+
37+
return () => controller.abort()
38+
}, [])
39+
40+
if (loading) return <p>Loading...</p>
41+
if (error) return <p>Error</p>
42+
43+
return <p>{data}</p>
44+
}
45+
```
46+
47+
```jsx
48+
async function ServerComponent() {
49+
try {
50+
const data = await fetch("/api/data").then(res => res.json())
51+
} catch (error) {
52+
return <p>Error</p>
53+
}
54+
55+
return <p>{data}</p>
56+
}
57+
```
58+
59+
Even in this very simple example where the client component is fetching data in the simplest way possible you still have to write tons of complex React specific code. With server components, though, this code is much simpler to understand and write since it works like normal JavaScript code.
60+
61+
The reason this code can be written so simply is because server components are rendered entirely on the server and the HTML output of that component is sent to the client as plain HTML. This means that when a user requests a page that renders a server component they will be sent down the HTML of that server component after it has already been rendered on the server. That HTML is then hydrated on the client and React takes over from there.
62+
63+
## Benefits Of Server Components
64+
65+
Server components are an incredible tool that makes data fetching much easier as we have already talked about, but there are tons of other amazing benefits that come with server components.
66+
67+
### Security
68+
69+
Since server components are run entirely on the server you can safely use secret API keys or fetch data directly from a database since the client will never see this code.
70+
71+
```jsx
72+
async function ServerComponent() {
73+
const user = await db.users.find({ name: "John" })
74+
75+
return <p>{user.name}</p>
76+
}
77+
```
78+
79+
This may sound like a minor bonus, but this is actually a huge deal since it means you don't need to create a seperate public API just to power your React application. You can just make all your database calls directly from your server components.
80+
81+
### Performance
82+
83+
There are actually multiple ways that server components increase the performance of your application.
84+
85+
#### Caching
86+
87+
Since all your code is run on the server it means you can cache data between requests and between users. For example, if you have a list of blog articles that you know doesn't change often you can cache that list of articles and serve it to every user without having to fetch it from the database every time.
88+
89+
```jsx
90+
async function ServerComponent() {
91+
// Cache for 1 minute across all requests
92+
const articles = await cache(db.articles.findAll, { timeSec: 60 })
93+
94+
return <p>{articles.length}</p>
95+
}
96+
```
97+
98+
#### Bundle Size
99+
100+
Another huge benefit is that since server components are rendered on the server you don't need to send any JS code to the client for those components. This drastically reduces the bundle size of your application and makes it much faster to load.
101+
102+
#### Page Load Speeds
103+
104+
Since server components are rendered on the server it means that the HTML for those components is sent to the client as soon as the user requests the page. This means that the user will see the content of the page much faster than if you were using client components since the client components need to wait for the JS to load before they can render. This is very important for SEO since Google highly values page load speeds.
105+
106+
### SEO
107+
108+
Speaking of SEO, server components are also much better for SEO since the HTML for those components is sent to the client immediatley without having to wait for JS to load. This helps search engines index your pages and makes them easier to find on Google.
109+
110+
## Downsides Of Server Components
111+
112+
Just like eveything in life if it sounds too good to be true it probably is. Server components are no exception and there are a few downsides with using them.
113+
114+
### No Interactivity
115+
116+
Since server components are rendered on the server it is impossible for you to have any interactivity in your server components. This means you cannot use React hooks, event listeners, or any other code that involves user interaction.
117+
118+
This may sound like a deal breaker, but since you can easily nest normal client components inside server components this is really not a problem.
119+
120+
```jsx
121+
async function ServerComponent() {
122+
const articles = await db.articles.findAll()
123+
124+
return articles.map(article => <Article article={article} />)
125+
}
126+
```
127+
128+
```jsx
129+
"use client"
130+
131+
// This is a normal client component so you can use hooks and event listeners
132+
function Article() {
133+
const [likes, setLikes] = useState(0)
134+
135+
return (
136+
<div>
137+
<p>{article.title}</p>
138+
<p>{article.content}</p>
139+
<button onClick={() => setLikes(l => l + 1)}>Like</button>
140+
<p>{likes}</p>
141+
</div>
142+
)
143+
}
144+
```
145+
146+
<Tangent>
147+
You may have noticed the `"use client"` string at the top of the client
148+
component file. This is a feature of Next.js specifically and is used to tell
149+
Next.js that this file is a client component. Other frameworks may have
150+
different ways of doing this, but the concept is the same.
151+
</Tangent>
152+
153+
As you can see in the above code we are able to use server components to fetch our data and then use client components to add interactivity to that data. This is a very powerful pattern and makes it much easier to write complex applications.
154+
155+
### No Browser APIs
156+
157+
Another downside is you cannot use any browser APIs in server components since they are rendered on the server and have no access to client APIs. This means things like `localStorage`, `navigator`, and `window` are all unavailable in server components. This again isn't a major problem since you can just use nested client components to access these APIs.
158+
159+
### Cannot Easily Be Nested In Client Components
160+
161+
Server components cannot be nested inside clients components. This is somewhat obvious as a client component is rendered on the client so you cannot also have a server component inside of it.
162+
163+
```jsx
164+
function ServerComponent() {
165+
return <p>Hello Server</p>
166+
}
167+
```
168+
169+
```jsx
170+
"use client"
171+
172+
function ClientComponent() {
173+
return (
174+
<div>
175+
<p>Hello Client</p>
176+
{/* This will not work */}
177+
<ServerComponent />
178+
</div>
179+
)
180+
}
181+
```
182+
183+
You can partially get around this problem (at least in Next.js) by passing the server component as a prop to the client component and then rendering it inside the client component.
184+
185+
```jsx
186+
function ServerComponent() {
187+
return <p>Hello Server</p>
188+
}
189+
```
190+
191+
```jsx
192+
"use client"
193+
194+
function ClientComponent({ children }) {
195+
return (
196+
<div>
197+
<p>Hello Client</p>
198+
{children}
199+
</div>
200+
)
201+
}
202+
```
203+
204+
```jsx
205+
function AnotherServerComponent() {
206+
return (
207+
<ClientComponent>
208+
{/* This will work */}
209+
<ServerComponent />
210+
</ClientComponent>
211+
)
212+
}
213+
```
214+
215+
For the most part this is not often something you need to do, but if you find yourself in this situation this is a good workaround.
216+
217+
## How To Use Server Components
218+
219+
Server components are still very experimental and thus are not able to be used directly inside of React. Instead you must use a framework that implements server compoents to use them. Currently the only framework that implements server components is Next.js, but many other frameworks are experimenting with implementing server components.
220+
221+
In Next.js specifically all components you create are server components by default. In order to use a client component you must opt into it by adding the `"use client"` string at the top of the file.
222+
223+
```jsx
224+
"use client"
225+
226+
// This is a client component
227+
function ClientComponent() {
228+
return <p>Hello Client</p>
229+
}
230+
```
231+
232+
The reason for this server first approach is because server components are almost always better to use unless you specifically need interactivity or browser APIs.
233+
234+
## Conclusion
235+
236+
Server components are a new way of writing React applications that make it easier than ever to create complex applications since they solve many of the complexities around data fetching and performance. Although, Server components are still very experimental, frameworks like Next.js make server components accessible in a stable way.

0 commit comments

Comments
 (0)