Aravind Balla/writings

Don`t Fetch JSON

February 05, 2019

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.

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

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

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

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.

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;
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}

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 who is a cool human, building things for himself, and sometimes for others. You should hit him up on Twitter!