How to structure your files in a large React application — the problem.

damusnet
5 min readJul 6, 2018

--

As a freelance developper I have had the chance to work on a multitude of React and React Native applications over the last three years. More often than not, it was by joining and collaborating on some existing project. Every single time, as the codebase would grow larger, we would experience the same pain around naming files, tracking dependencies, locating a particular piece of code we needed to work on, and so on. As a result, bugs would creep in, development would slow down, ultimately to the point where someone would suggest starting from scratch.

A traditional file structure

Every codebase I’ve encountered started this way:

A code editor with a src folder containing the actions, components, containers, and reducers folders

At first this looks fine. components and containers is where you put your presentational and container components. actions and reducers is where you put, well, your actions and reducers (in a standard redux environment).

Soon to be bloated

Naturally, not everything fits within those four folder, so maybe you have a lib or a utils folder. Maybe both? Soon, someone decides that thunks are not enough, and they want to try out sagas. Of course you write unit tests, with any luck with Jest. You have also heard about the awesome Storybook and have stories for most of your presentational components. Finally, you just have to try the new hotness, GraphQL, and it comes with it’s own queries.

Now the situation looks a little more like that:

A code editor with a src folder containing the actions, components, containers, lib, queries, reducers, sagas, stories, tests, and utils folders

At this point, you might be wondering what is wrong with this screenshot. And maybe there is nothing wrong. I mean, where you put your files doesn’t really matter. Things still work. Code still runs. But let’s look at what happens when we start working on the actual files.

Folders are tightly coupled

As an example, let’s build a ticketing website. It will have a Layout, a Homepage, an Artist page, a Venue page and a Search page. It should probably have much more things, like an Event page and a Checkout page and your Account settings and such, but hey, this is just a random contrived example.

The story, all names, characters, and incidents portrayed in this production are fictitious.

Now imagine the time comes, you just got a new Jira ticket assigned to you, and you need to make a change to the way the Artist fetches data. Here are all the folders you will need to open:

The same code editor as before, but with the actions, containers, queries, and reducers folders expanded

I’ve left out sagas and tests because it would not fit on my screen otherwise. Can you count how many times the word Artist appears? Four times! And four times Home, four times Layout, four times Search, four times Venue, and so on.

But what about when we are working on a presentational component? We need to update the Header component, which is shared between Artist and Venue page. We want to open the component itself, the story and the unit test associated. It looks something like that:

The same code editor as before, but with the components, stories, and tests folders expanded

I don’t know about you, but my head already starts to hurt! Just locating which files I need to open to even get started working on something is daunting. Of course a lot of this can be made easier by your code editor. Just open one file and then click on imports to open the other ones (except that your component doesn’t reference its own stories or tests).

Hard to navigate

You also probably know all your code like the back of your hand. You know exactly where to find which file. You know exactly which component has a unit test or a story and you never break any. You never have any merge conflict either.

But what about that new developper that just joined your project? How do they decide where to put that new component? Is it a container or a presentational component? Are you even sure how to decide that? And what about the you that comes back after a full week of vacation and has completely forgotten how to write a render prop?

And yet, we’ve got no code here

Note also that I was able to fill the file structure with basically no code, and lots of missing pieces. There is only one shared component there for instance. Where are all the Buttons, Icons and our beloved Modal? And because I’m a peaceful person, I won’t even try to bring styling in the mix. Who needs css anyway? There is also no mocks, no shared prop types, no nothing.

One last example to illustrate how naming can be difficult. Let’s imagine that the Layout, Artist and Venue pages all have some sort of Footer. But they actually are very different. How do you name the files and the components?

The same code editor as before, but with the artist, layout, and venue folders expanded in the component folder. They all have a file named Footer.js that exports a Footer React component.

So let’s find a solution!

This structure has three major issues in my opinion:

  1. It makes code that belongs together hard to discover
  2. It leaves too much room for inconsistent naming
  3. It makes reusing and refactoring components difficult

In the next article we will try to solve them with a different approach. Keep reading for How to structure your files in a large React application — the solution.

Many thanks to Julien and Guillaume who read drafts of this post and helped me improve it.

--

--