Data Loading with SSR in React
Tags: react, javascript, webdev, ssr
Published: 2021-09-20 07:26:39

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

Note: you can access source code of this article [here](https://github.com/reza899/ssr-data-load).


## 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](https://dev.to/alain2020/ssr-vs-csr-2617) 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"]
}
```

`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");
});

```

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;
    res.json(loadedCoins);
  });
```
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](https://rapidapi.com/Coinranking/api/coinranking1/)), 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(() => {
    fetch("/api/coins")
      .then((res) => res.json())
      .then((data) => setCoins(data));
  }, []);

  return (
    <>
      <h1>Server-side Rendering</h1>
      <ul>
        {coins &&
          coins.map((coin, i) => {
            return (
              <li key={i}>
                {coin.name} - {coin.price}
              </li>
            );
          })}
      </ul>
    </>
  );
}
```

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 reza899/ssr-data-load no-readme %}