DEV Community

Cover image for Data Loading with SSR in React
Reza Bozorgi
Reza Bozorgi

Posted on

Data Loading with SSR in React


In this article I want to check out how data loading works in SSR.

Note: you can access source code of this article here.

What is Server-side Rendering(SSR) ? ๐Ÿค”

With server-side rendering, the server is the one that takes care of running our scripts and rendering all of our elements. (see this describe thoroughly about SSR and differences with CSR)

Setting up a simple server

First of all, we need to have a server. By using classic CRA, installing few packages and adding two files below in the root folder simply we can have a express server.

To take modern code and convert that into something which is understandable for Nodejs should use babel and it's related presets:
npm i -D @babel/core @babel/preset-env @babel/preset-react @babel/node nodemon

Then, install express to serve our app:
npm i express

We also need an optimized production build by running npm run build.

.babelrc file:

  "presets": ["@babel/preset-env", "@babel/preset-react"]
Enter fullscreen mode Exit fullscreen mode

server.js file:

import express from "express";
import React from "react";
import { renderToString } from "react-dom/server";
import path from "path";
import fs from "fs";
import App from "./src/App";

const app = express();

app.use(express.static("./build", { index: false }));

app.get("/*", (req, res) => {
  const reactApp = renderToString(<App />);

  const templateFile = path.resolve("./build/index.html");
  fs.readFile(templateFile, "utf8", (err, data) => {
    if (err) {
      return res.status(500).send(err);

    return res.send(
      data.replace('<div id="root"></div>', `<div id="root">${reactApp}</div>`)

app.listen(8080, () => {
  console.log("Server is listening on port 8080");

Enter fullscreen mode Exit fullscreen mode

For running the server you can use nodemon in order to restart after a change automatically:
npx nodemon --exec npx babel-node server.js

When should we load data?

I'm going to look at how data loading works with regards to server-side rendered applications.

To show data loading with server-side rendering let's add some coins ๐Ÿ’ฒ to our server.

In server.js file I'm going to add a special API route that our front-end will be able to use to load the coins data.

const coins = [
    { name: "Bitcoin", price: "47000" },
    { name: "Ethereum", price: "3300" },
    { name: "cardano", price: "3" },

  app.get("/api/coins", (req, res) => {
    const loadedCoins = coins;
Enter fullscreen mode Exit fullscreen mode

What I'm going to do, is just send back to the client some fake coins that will define in an array. Normally, you'd want to read these from a database or API (e.g. RapidAPI), but just for simplicity sake, I'll define them right in our source code.

So our front-end now will be able to load the coins from this endpoint. So let's load our data inside a useEffect hook.

function App() {
  const [coins, setCoins] = useState();

  useEffect(() => {
      .then((res) => res.json())
      .then((data) => setCoins(data));
  }, []);

  return (
      <h1>Server-side Rendering</h1>
        {coins &&
, i) => {
            return (
              <li key={i}>
                {} - {coin.price}
Enter fullscreen mode Exit fullscreen mode

Let's build our front-end by npm run build.

If we inspect the HTML that we got back from the server, what we're going to see does not actually include the coins. why? ๐Ÿ˜ฎ

What's happening is, the server is server-side rendering the front-end, except for the parts where we need to load data.๐Ÿ˜‰

GitHub logo reza899 / ssr-data-load

how data loading works with regards to server-side rendered applications

Top comments (0)