Client-Side Rendering (CSR)

With server-side rendering, the pages are generately very quickly (hopefully!) on the server-side and sent to the client ready to view. However, if you want the content to be dynamic and interactive, there needs to be client-side JavaScript that runs and makes this possible. You could simply serve a script alongside the document, and in fact this has been done on all of these example pages - the script handles the timer that counts down at the bottom of the page.

This is fine for something very simple, but what we really want is to leverage JSX - which we are already using for server-side components - with a tool like React to develop complex interactivity on the client-side.

This is exactly what Next.js does. It allows you to use React everywhere, for server-side or client-side components. The client-side components are pre-rendered on the server, like the server-side components (and unlike a traditional React app), and then they are hydrated with JavaScript on the client side to make them interactive. This is very powerful. Let's go through some examples.

Here is the same "note viewer" from the server-side pages, with a color slider added that lets you change the background color. This is silly, of course, but illustrates the interactivity of the client-side element:

Try it by updating the note here and refreshing this page.

This is the content of that note, according to this page:
Change this text!  Bleh!!!
And this is the value of "lastUpdated" for the note:
Wed Apr 10 2024 16:53:14 GMT+0000 (Coordinated Universal Time)

The pseudo-code for this page is:
"use client"; 
export default async function CSR({}) { 
    const [data, setData] = React.useState("Loading..."); 
    fetch("/api/data").then(res => res.text()).then(setData); 
 
    return <div> 
        The content of this page: {data} 
    </div>; 
} 


*Actually, in Next.js client-side components are still initially rendered on the server side.
Consider a traditional React app - you can try this by running npx create-react-app in your terminal and looking at the boilerplate project it creates.
The page will look something like this:
React app website example

But if you open your dev tools and inspect the document request that is made, the body of the html is simply this:
React app html example

The way this works is that the JavaScript for the page includes these lines:
React app javascript example

This takes that html element and puts all of the magic of React inside of it, including all of the DOM elements, the event listeners, etc.
Next.js still runs React on the client side, so your client-side components can be written just like a normal React app.
However, if you open the dev tools on the page you are reading right now, refresh it, and look at the document request in the Network tab, you will see that the html is already fully rendered, unlike a plain React app.

This is the whole idea of Next.js - we really want to deliver something to the client as fast as we possibly can, so even for a 'client-side' component we actually render a static page first.
The page THEN gets 'hydrated' with the JavaScript, and becomes a fully interactive React app.

The Next.js-specific directive "use client" has been added to the code for this page, which tells Next that this is a client-side component.
This means that the page is rendered very similarly to a traditional React app - the barebones html template is sent to the client, and then the javascript (React) runs to make requests for the page data and generate the content.

This page loads with some "Loading..." placeholders, then sends a fetch request to get the note content, and uses React.useState to re-render the page content when the response is received.
This happens on the front-end*, just like a normal React app. If you use your browser dev tools, you can see the 'favouriteNote' request being made.

This is very different from the other pages which were server-side rendered. On those pages, the content could be directly fetched from the database, without any additional fetch request needed.
In fact, the stoats had to add a GET endpoint to the server just to make this example page, because the main application doesn't require one!

You can see this process in action with the content displayed below. On this page, a delay has been added to make the process more visible.

Back
5