Shivek Khurana

@shivekkhurana

Fractal — A react app structure for infinite scale

September 23rd 2017

After having worked with React and flux (Redux) with over 8 significant projects (100+ screens each), we learned a few things about React apps.

Over time, a way of structuring projects evolved, which was so natural that on-boarding new frontend developers (with next to 0 experience with React), became a piece of cake.

We call it the Fractal. It is (and will always be) a work in progress.

Fractal allows you to:

  • Reason about the location of files
  • Manage and create complex user interfaces
  • Iterate quickly
  • And scale repeatably

Rather than being a set of rules or conventions, the essence of Fractal can be summarised in just one guiding principle: All units repeat themselves.

The app layout

Think of your app as a tree (data structure), every project gives a new shape to the tree, but the roots nodes remain constant. The root nodes is the app layout. These are shown in the screenshot below.

App Layout (Check the sidebar, it shows all the files)
  • Pablo is the name of the product.
  • build is where all the built files go, you never touch this except when you need to deploy.
  • public is where your index.html file and <script src> assets go. (They automatically get copied to build while using create-react-app)
  • src is where you code.
  • src.pages are the root level components, ones which are directly mounted on level 1 routes. (Ex. if you have a route called /login that mounts a Login component, then Login.js will be present in pages directory).
  • src.modules handles your state (actions + reducers using ducks file structure).
  • src.components have shared components, like Button, Input etc.
  • src.utils have utilities like your API wrapper, date utils, string utils etc.
  • config is where you store your environment variables like API endpoints. Don’t commit this to git.
  • store initializes the redux store.
  • index registers the routes and renders the app.

We don’t have the concept of smart and dumb components, because we found that idea to be limiting.

The Fractal pattern: make all units repeat

The magic happens when you try to leverage the power to compose React components.

A typical login screen

Assume a login component that gets mounted on /login, has a form, and a forgot button that opens a password reset modal.

For the sake of this example, we break this down into 3 components :

  • Login.js
  • Form.js
  • ForgotModal.js

This will be structured as follows :

Simple Fractal Structure

The Pages directory have a Login.js component.

All components are CamelCased.

The sub-components of Login.js are present in a folder called login. This is the node that will help set up a repeating pattern.

All nodes are lowerCamelCased. So login in this case. If ForgotModal.js had another sub-component to show a success message, then we can have a folder named forgotModal in the login node, and place the SuccessMessage.js component there.

Fractal keeps repeating itself.

The following screenshot shows what it looks like in a real app.

pages have two roots: Document.js and Template.js and two sub-nodes document and template

All components required by a page go to its node folder. If the component is required by more than one components, like a branded button, then it goes to the src.components folder. When you need to break down a component into sub-components, use the Fractal. The screenshot below shows how we use The Trackers component in the same way.

Observe a file Trackers.js and a folder named trackers, containing all sub components required by Trackers.js

The Fractal State

It turned out to be a sound practice to manage components in the Fractal pattern, so we asked ourselves if we can do the same for the state? (Yes we can.)

We use redux in our examples. Assume a design where your frontend has to show a list of apps, each of which can have many reviews. A classic one to many details flow. In standard redux, we can have two reducers, one for [C]reating, [R]eading, [U]pdating and [D]eleting apps and another for CRUDing reviews.

Because we use the ducks file structure, we are supposed to have an apps.js file and a reviews.js file in our modules folder. But this will not help us emulate the shape of the API, and as the size of the codebase grows, it becomes hard to reason for a flat store.

Instead, we use the Fractal state to save our modules as follows :

Fractal on modules. Observe the modules folder on the left sidebar and the shape of the store on the right (line 9, 10, 11)

With the design above, we can emulate the shape of the database directly in our stores.

Q. Ask yourself, if along with reviews, each app had reviewers object as well, where will the module for reviewers go?

A. If you chose to put it in the modules.app folder, then you understand Fractal right.

This gives us a phenomenal scale. Imagine each review had a source associated with it, which was to be fetched from a separate API. All we need to do is create a review folder in modules.app and add a file named source.js to it and inside the combineReducers on line 11, add another key = review and value = combineReducers({source: reviewSource}).

The background

The idea of the Fractal was coined by my mentor Kapil Verma. This idea was successfully implemented in Express based APIs, and was borrowed by me to create scalable react apps.

This has worked well for us in all kinds and sizes of apps. We are even experimenting with the Fractal pattern on our python code bases.

A note for advanced developers

  • One thing to note is the absence of index.js inside folders. This causes conflicts with module resolution (because of the casing).
  • All imports in the example are absolute as a convention (we prefer absolute). They can be relative if you wish.

Update 1:

A few readers asked for sample code. I’ve managed to put a little something together.

Update 2 (July 30, 2018):

This article has just exploded. I see this mentioned on so many subreddits and git repos. People have emailed me and asked me questions about Fractal. I’m honestly humbled and delighted to be able to payback with my knowledge.

To continue this effort, I’m planning to start a slack community. This will enable you to ask questions(about Fractal and React) related to your use case. It will also give you access to me and other developers (at various skill levels) in real time. You can join it here.

If you liked this article and want to stay updated, follow me on: Medium, Instagram or Twitter

You might also like:

More by Shivek Khurana

More Related Stories