React folder structure explained with mental models
Try to remember that last time you moved to a new place. Moving is not only time-consuming (in practice several years before you get settled), but also contributes to stress, deadlines to be met and money to be spent.
PART 1: THE PROBLEM
Several years after you moved, you start to feel like home again. Several years of refurnishing, throwing out old stuff and buying new stuff that is. This is difficult and requires a lot of thought. Furnishing is a college degree.
(Yes: this is an article about React, hang on)
Not to mention, the actual moving out part. Everything has to be put in boxes, labeled correctly and carried out. In theory, you should label all the boxes accordingly to its content. That way it’s very convenient to unpack at the new location.
This is, of course, a lot harder in practice. An items position may be ambiguous. The box may be half full, left with the option to either waste the extra space and close it. Or, you could fill the space with items that do not match the label name on the box. Similarly, you could be out of boxes, forcing you to reuse others causing naming conflicts.
You may have already have come up with ideas for solving stated problems, and accordingly so, these are not that difficult.
Perhaps we could just live with our stuff in the boxes all the time?
In this way, you could just carry our boxes into a truck or car, whenever you move next. Sure, some system has to be developed: the labels on the boxes must match perfectly with its contents. Maybe a database with QR-codes will do the trick. Search up what you need in a database, or ask “Alexa, which box contains my vacuum cleaner?”.
This is borderline thought-exercise, but it works in terms of a metaphor for your React project. The magic place where we could destroy rooms (read: web pages) in seconds, and use its components to build another.
PART 2: THE CLARIFICATION
Developing web apps is for many, a one person job. Job offerings for React freelancers are higher than ever. These types of jobs may not always offer well thought through development plans, or even what the visual design should be. Leaving you, as the developer, in with the task of designing, prototyping, and programming as a lone wolf in the winter mountains.
The moving-out-metaphor given above suits well into these kinds of jobs where practically nothing is decided beforehand. It will require you to move in and out of different prototypes as the path forward emerges right before your feet. Your well thought out state flow, and structure will have to be re-written multiple times. Coming from experience: you may survive this a couple of times, but this shit will lead you right down a path where everything is made of spaghetti. And although spaghetti can be incredibly delicious, you do not want your code to resemble it.
Part 3: THE “SOLUTION”
I have come to think about my project as if it were to be played out as a theatre. So appropriately, the project should be structured as one.
Every scene in a theatre probably requires new props. Sometimes a new scene has a change of environment; forcing the theatre to have a pause, or using strategies to quickly exchange the bigger components for more appropriate ones. Similarly: as a reaction to our user’s action, we must respond with new components. This is easy when we have already loaded every component on the user’s device, just swapping one with another as our state changes.
However, sometimes the new app state will require such a huge change, it’s easier to just swap out everything. We have to quickly set a new scene for our user. We do this in rendering a new scene, using react-router or something else.
Managing scenes is difficult. Arbitrary theories on how we should manage it: giving us no real answers; just a lot of if/then statements. But with a mental model on project structuring, this comes to us very naturally.
Your current structure is probably based on the person you learned React from, or you’ve learned with experience. You may have read articles like this one, which is very clear about how exactly you should structure React. However, every project is different and requires alterations.
A mental model gives you a sense of understanding: naming conventions, where and how to put your new component becomes effortless.
So, on to how exactly we can structure the project, I want to present a few examples on to how you can begin.
Let’s start with the naming convention of scenes. Try to capture what the purpose is of that scene is present. Such as UserProfile, Login, Signup, etc. Our top-level folder requires a subfolder that handles these scenes. Name it scenes. Since everything is just boxes in a theatre, think of it like this image:
It makes sense that every scene requires components. These components may require content files, such as images. Let’s put these content files in a new subfolder called assets.
If needed, include a folder called utilities. This is where we should keep things that are useful for our scene, but which position is arbitrary. Such as data objects.
The scene may be handling a service, such as if the scene is logging in or signing up a user. Create then a folder called service, and put strictly the files in charge of the service here.
Last but not least: every scene should have its own index file to connect the whole scene together. By default, keep this file as the only file in a scene which is allowed to render something.
Given stages of development where our path forward is very short-sighted: it makes sense to restrict adopting components outside the scene. This gives us the ability to quickly refactor or delete scenes along with its components. If there are components required to be rendered in every scene, consider rendering it at the top level index file.
Following this train of thought, we end up with a structure where prototyping is an ease. Unlike the moving in and out metaphor, this gives us the ability to maintain a tightly structured project without much effort. Even to take a scene from one app, and move it into another is effortless, primarily because each scene has its own assets, components and an index.
To finish this off, I have mentioned the “top-level” folder a couple of times without much more to it. And in fact, it is not much to it. Consider it as a scene of itself. It has an index, which is the index that renders every other scene’s index. If you use redux, react-router or something similar, this file is in charge of implementing those. Since I also previously stated that: components rendered at every scene should only be rendered in this file, such as appBars, the top level folder requires a components folder as well.
Moreover, the top-level index may require data objects, images, etc. Which means it may have its own utilities and assets folders.
Thank you for reading,