How to build a React SSR app without any tooling or framework

Image for post
Image for post
Source: Reddit and Dilbert by Scott Adams

This is the first in (hopefully) a series of articles to document the lessons I learned building and maintaining SSR apps.

This article does not cover the pros/cons of SSR, or the pros/cons of not using tooling or frameworks (e.g., Create React App, Next.js, etc).

I fully acknowledge that manually setting up build configs is painful. There is plenty of great tooling out there to abstract away these configs, so you probably don’t even need to touch any of this stuff to build awesome apps.

But for those ready to embrace the pain…


Let’s start with the basics. We will use React, webpack, and Express to build an SSR app that works as…

Part 2: A further exploration of the Hooks, Render Props, and HOC patterns

Image for post
Image for post
c. 1512, Oil on canvas, Source:

In Part 1, I presented an approach to decouple the data fetching/management layer from a React component that renders some UI based on the data, which would free us from being locked into any particular data library or framework. Let’s call this Approach A.

Approach A. Custom Hook

Let’s create a custom hook — useSomeData — that returns the properties someData, loading, and error regardless of the data fetching/management logic. The following are 3 different implementations of useSomeData.

With Fetch API and component state:

With Redux:

With Apollo GraphQL:

The 3 implementations above are interchangeable without having to modify this UI…

And reduce the size of your future PRs with the Open/Closed Principle

Image for post
Image for post
KNOW YOUR ENEMY (image by Klara Kulikova, meme from Programming Memes)

Suppose I use an external service provider to process payments for my E-commerce app, and I need to embed some external SDK code to integrate the payment service into my app.

In this oversimplified example, let’s say the payment service is responsible for checking whether a given payment method (e.g, Apple Pay and Google Pay) is available based on the customer’s device, region, etc. While my “core” UI component PaymentOptions is responsible for rendering the available payment methods as options. Lastly, I want the flexibility of adding new payment methods in the future (for 📈💰reasons).

I can write it this way. …

And how I “program to an interface” with JavaScript functions

Image for post
Image for post
Source: Imgur

I‘m certain you have seen (or written) this common React pattern: (a) render a placeholder/ loader/spinner while some data is fetched via AJAX, then (b) re-render the component based on the data received. Let’s write a functional component leveraging the Fetch API to accomplish this.

Let’s say my app grows, and there are X components that use the same data fetching logic because… reasons. To avoid spamming the server with data requests, I decide to use Local Storage to cache the data.

OK… does that mean I need to update the data logic X times? 😬😱

Nope, let’s DRY it up by writing a custom hook useSomeData. …

What’s a JavaScript Promise? It’s when code vows to work every time.

Image for post
Image for post
Shoutout to Cassidy Williams 😀

Let’s create a button that will:

  • perform an expensive synchronous operation,
  • fire 2 AJAX requests, and
  • update the DOM based on the AJAX responses.

Here is the markup.

Here are the functions. Let’s also measure the duration of each operation with the Performance API, which visualizes when and how long each function executes on the Chrome DevTools Performance Timeline. (Thanks to JSONPlaceholder for the dummy endpoints.)

You’re still here? Good, here comes the interesting part: writing the onclick handler for the button. Since all the cool kids are doing it, let’s use async / await.

async function handleClick() {
someSyncOperation(); // Expensive sync operation…

Making the web accessible one (less) DIV at a time.

Image for post
Image for post
Source: Make a Meme

I used to think that accessibility is at best a UX improvement, and at worst “compliance work”. But as the pandemic turned into an essential service for many of our customers, I have read a good number of heartbreaking customer service tickets that revealed my biases and the unintended exclusions caused by my code. Now, I’m convinced that making the web accessible is the right thing to do.

Accessibility is a broad topic, and a subset of loftier inclusive design principles that I won’t pretend to be an expert on. …

What’s up? Oh nothing, just doing `this` and `that`.

Image for post
Image for post
Source: Programmer Humor

This is a spiritual sequel to this article.

Create a class with a method using Traditional function like so. Let’s call this Approach A.

// APPROACH Aclass SomeClass {
constructor() {
this.someProp = 'someValue';
someMethod() { // Traditional function

Create an instance of that class. When invoking the method on the instance, this refers to the instance. So far, it’s behaving as expected.

let instance = new SomeClass();instance.someMethod(); // logs 'someValue'

But, as soon as we assign the method to a variable and call that function variable, the method loses its context, and you get Uncaught TypeError: Cannot read property ‘someProp’ of undefined.

Debugging: a classic mystery game where you are the detective, the victim, and also the murderer.

Image for post
Image for post
Image source: Programmer Humor

Here is an explainer of how cookies work. TLDR:

  • Browser sends HTTP request to server.
  • Server sends HTTP response with Set-Cookie: cookie=monster header, which sets the cookie in the browser.
  • Every subsequent request the browser sends to the server will have the Cookie: cookie=monster header.

I store a CSRF token in a cookie, which is used by the server to validate client-side HTTP POST requests. The server responds with a 403 if the cookie is missing in the HTTP request.

On the client-side, I have been using the cross-fetch package via the ponyfill approach.

import fetch from 'cross-fetch';fetch('/some-route', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
body: { /* some payload */ }…

My first of (hopefully) many stories where I expose how little I know about coding and share the lessons I learned (or re-learned).

Programmers in 1960s writing software to fly rocket to the moon, versus programmers in 2020s struggling with VIM text editor.
Programmers in 1960s writing software to fly rocket to the moon, versus programmers in 2020s struggling with VIM text editor.
Image source: Programmer Humor

When defining a method on an object, we presumably want this to refer to the object on which the method is defined.

const someObj = {
someProp: 'someValue',
someMethod: function() {
someObj.someMethod(); // will log 'someValue'

Since all the cool kids do it, I use destructuring assignments all over the place. However, destructuring a method from an object causes it to lose its original context. In other words, when invoking a destructured method, this no longer points to the object on which the method is defined.

const someObj = {
someProp: 'someValue',
someMethod: function() {
console.log(this.someProp); …


Suhan ⛄️ Wijaya

Right-brained techie passionate about coding, product, UX, and fun adventures with my family. Let’s connect on

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store