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.
javascript1app.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.
javascript1// middleware.js2exports.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`;1011 if (req.path.match(/\/getcomp/)) {12 res.send({ html });13 return;14 }15 next();16};1718// server.js19app.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
.
javascript1import React from 'react';2import { fetchComp } from './api';34function createMarkup(text) {5 return { __html: text };6}78class SSRComp extends React.Component {9 constructor(props) {10 super(props);11 this.state = {12 html: '<p>loading<p>',13 };14 }1516 componentDidMount() {17 fetchComp().then((html) => this.setState({ html }));18 }1920 render() {21 const { html } = this.state;2223 return <div dangerouslySetInnerHTML={createMarkup(html)} />;24 }25}2627export default SSRComp;28
javascript1export 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 👋
By Aravind Balla, a Javascript Developer building things to solve problems faced by him & his friends. You should hit him up on Twitter!