Separation of concerns in a React App

Image by bluebudgie from Pixabay

Bootstrapping an application with several global dependencies can be tricky. Internationalization, Authentication, Component library, Theme, Routing, State management, Session management, Error Boundaries etc are some of the pieces you will need to provide throughout your React App.

In this article I’ll try to present a pattern to separate concerns in a clean way. There are no original ideas here. The essence of it is derived from blogs by Eric Elliott and Kent Dodds.

The end result would be something like this:

What I want to demonstrate is the how simply and nicely it is expressed. App has two personas. One that is authenticated and one that is not. Both require a different combination of global bootstrapping. The secret to this is how you write your HOC wrappers.

The HOC Wrappers

Here are some examples of Higher Order Components. These are not copy-paste ready but just a general guideline.

Set up i18n

Set up react-router

The common UI pieces that envelops the App features

Protect your feature from crashing the full app. There is a nice example available here:

For example.

If you have noticed, all these HOC wrappers have the same function signature:

This means that you can compose them very nicely. An authenticated page will have different set of concerns than an unauthenticated page, such as Redux. You can compose two different Page behaviors:

Now it becomes very straightforward to setup your App:

This pattern provides a clean way to compose your app features inside a certain Context. You can augment some of these contexts by providing custom useContext() hooks. Say you want to use the logged user name in other parts of the app. For libraries such as Redux, the context is already provided and the hooks provided by the library is enough.

As simple as that. Hooks in libraries such as Redux will readily work once you’ve enclose the app in its Context Provider.

What is presented in this article is a simple yet powerful pattern that can bootstrap a ReactApp with very isolated, loosely coupled implementations. Extending them or adding new ones become very easy. All you need to do it is to create a HOC and compose it as shown above.

You can also use this pattern to create multiple global contexts and make them available to features in the app via hooks. More on that in my next article on State Management.

Frontend Architect, San Jose, CA