React Server
Components
Client Apps (SPA)
- Wait until all of the components are ready and then render them
- Wait for everything
- The html that's rendered is the container
- JavaScript builds the rest
- A lot of work is put on the server
document.getElementById("root");
GET / bundle.js
render when ready
Client Apps (SPA)
Benefits
- Navigation without refresh
- Strong separation between server and client responsibilities
- Can achieve performance wins with lazy loading, code splitting, preloading
Drawbacks
- The bigger the bundle, the slower the app
- SEO Limitations
- Need additional help with data fetching/caching
Server Side Rendering
React Workshop
Starting in 4 minutes
Topics
- Props
- State
- Handling Data
Server Side Rendering
Benefits
- Less JavaScript (probably)
- SEO Enabled
Drawbacks
- If you reload the page (data fetching, server generated time, etc.), you still need to wait for those.
- Have to decide what is server rendered and isn't
- Doesn't prevent the server from being slow
Server Components
How does this work?
Not everything is interactive, most can be server rendered
* React components are run on the server
* HTML output is sent directly as the source
Data Streaming Format
* string representation of the Virtual DOM
if there are client components, this describes where to insert at runtime
Reconciliation
Works similarly to handle updates
But console errors are thrown if there is a mismatch
benefits
move data fetching to the server
smaller bundle size
can refetch without getting rid of client side state
but... you're probably going to need a framework to see the benefits
Next.js
App Router - server components by default
opt in to client components with "use client"
If something is specified as a client component, it's still pre-rendered and included as static output -- SSR
Reconciliation still happens to diff the DOM created from static HTML with the virtual DOM
Next.js
When a route is loaded with Next.js, the initial HTML is rendered on the server. This HTML is then progressively enhanced in the browser, allowing the client to take over the application and add interactivity, by asynchronously loading the Next.js and React client-side runtime.
progressive enhancement
Show the users the content that is ready
load interactive or data-reliant content in the background
"use client"
place it above the imports
for example, if Menu imports MenuButton, MenuSlider, etc, it is assumed that these are also client components
- Components in the Server Component module graph are guaranteed to be only rendered on the server.
- Components in the Client Component module graph are primarily rendered on the client, but with Next.js, they can also be pre-rendered on the server and hydrated on the client.
- The
"use client"
directive must be defined at the top of a file before any imports. -
"use client"
does not need to be defined in every file. The Client module boundary only needs to be defined once, at the "entry point", for all modules imported into it to be considered a Client Component.
server components don't read from React state
Which one should I use?
Client vs Server
useState, useEffect
Client!
Accessing backend resources
Server!
Browser only APIs
Client!
Auth details like tokens, API keys
Server!
Data Fetching
Server!
Event handlers (onClick, onChange)
Client!
RSC Do's and Do Not Do's
Make Client Components Leaves
Compose Client and Server Components
- On the client, React renders Client Components and slots in the rendered result of Server Components, merging the work done on the server and client.
- If any Server Components are nested inside a Client Component, their rendered content will be placed correctly within the Client Component.
Don't import server components in client components
Pass server components to client components as a prop
Keep client code out of server components
export async function loadData() {
const res = await fetch('https://mh.com/pets', {
headers: {
authorization: process.env.API_KEY,
},
})
return res.json()
}
What's the issue?
server-only
import "server-only";
export async function loadData() {
const res = await fetch('https://mh.com/pets', {
headers: {
authorization: process.env.API_KEY,
},
})
return res.json()
};
Error!
client-only
import "client-only";
function interactWithUserInWeirdAntiquatedWay() {
window.prompt("How are you? ");
};
Incorporating Third Party Libraries
Using directly in a Server component might not work
Can wrap in a client component to pass to server component
'use client'
import { MagicList } from 'magic-list';
export default List;
Context
(deep breaths)
Context of Our Youth
const App = function() {
return (
<Provider data={data}>
<Layout />
</Provider>
)
}
3rd party providers: Apollo, Redux, etc
Data Fetching
useEffect
Data Fetching
GraphQL - useQuery, useMutation, useSubscription
React Server Components
By Moon Highway
React Server Components
- 349