Don`t Fetch JSON

Banner image for Don`t Fetch JSON

Why should you though? This is not intended if you have an API endpoint (backend) serving multiple types of clients(like mobile and web).

Don't use this in production. It's just an experiment.

It is a small experiment to check whether you can directly get the html for the component instead of fetching the JSON data and populating it in the React Component. Express is used for server rendered React output.

Generally in SSR, we have the routing logic in the React application, using react-router or some similar kind of library. The server (Express in our case) returns the complete React application for all routes and does not worry about routing.

javascript
1app.get('*', (req, res, next) => {
2 // ...
3 // res.send(renderToString(<App />)
4});
5

Let's build a special route, say /getRenderedComponent, to give the rendered HTML as a response, as a middleware.

javascript
1// middleware.js
2exports.renderedCompMiddleware = (req, res, next) => {
3 const items = ['Milk', 'Coffee'];
4 const html = `
5<h2>Server rendered component</h2>
6<ul>
7 ${items.map((item) => `<li>${item}</li>`)}
8</ul>
9`;
10
11 if (req.path.match(/\/getcomp/)) {
12 res.send({ html });
13 return;
14 }
15 next();
16};
17
18// server.js
19app.get('*', renderedCompMiddleware, (req, res, next) => {
20 // ...
21 // res.send(renderToString(<App />)
22});
23

We included it as a middleware, so the request will pass through it. (This might not be the correct way of doing this. We should have a separate route for this).

At the middleware, we render the HTML. We can even use react-dom/renderToString and render a React component to send as a response.

This response can be consumed in a React component easily. Something which can fetch and render HTML inside it will do the job. Like our SSRComp.

javascript
1import React from 'react';
2import { fetchComp } from './api';
3
4function createMarkup(text) {
5 return { __html: text };
6}
7
8class SSRComp extends React.Component {
9 constructor(props) {
10 super(props);
11 this.state = {
12 html: '<p>loading<p>',
13 };
14 }
15
16 componentDidMount() {
17 fetchComp().then((html) => this.setState({ html }));
18 }
19
20 render() {
21 const { html } = this.state;
22
23 return <div dangerouslySetInnerHTML={createMarkup(html)} />;
24 }
25}
26
27export default SSRComp;
28
javascript
1export function fetchComp() {
2 return fetch('/getcomp')
3 .then((data) => data.json())
4 .then((comp) => comp.html)
5 .catch((error) => {
6 console.warn(error);
7 return null;
8 });
9}
10

I don't have an exact idea of where this can be put to a real production environment but was a successful fun experiment.

Thanks for reading through. Good day 👋

Aravind Balla

By Aravind Balla, a Javascript Developer building things to solve problems faced by him & his friends. You should hit him up on Twitter!

Get letters from me 🙌

Get a behind-the-scenes look on the stuff I build, articles I write and podcast episodes which make you a more effective builder.

Read the archive 📬

One email every Tuesday. No more. Maybe less.