Organizing your components can be a surprising challenge you'll face. While there's no single "right" way to do it, making smart choices early on will help your project's maintainability. Let's look at some approaches and best practices for structuring your components well.
One Component Per File
A common strategy is to stick to "one component per file".
My personal rule of thumb is one exported component per file, with files ideally less than 100 lines and not bigger than around 250 lines.
Let's walk through some examples to see how I arrived at this rule. Each of these examples do the same thing, but take different routes to get there.
Example 1: One Mega Component
In the first example, 01-one-component-per-file-large
, we take the layout from a designer or toolkit and drop it directly into the application code. The result is one mega component that is 850 lines long.
This approach takes the "one component per file" rule too far. It is unmaintainable and has terrible performance because any state change will cause the entire component to re-render. It needs to be broken up into smaller components.
Example 2: Nested Components (Don't Do This!)
In the second example 02-nested-components-do-not-do
, we break the component into smaller nested components inside the main component.
As seen in this screenshot of the code, the MobileLinks
component is nested inside the HomePage
component:
While this approach breaks the component into smaller parts, nesting like this is something you should never do!
The React documentation specifically warns against this practice because it kills performance. Every time the main component re-renders, there's a new reference to each nested component, breaking React's caching and forcing it to re-render everything inefficiently.
Example 3: Single File with Smaller, Non-Exported Components
In the third example 03-one-exported-component-per-file
we have a single file with smaller, non-exported components. The main exported component is at the end of the file, while the other components are not exported by the module.
This approach provides good privacy, as the components that shouldn't be reused are not exported. However, the downside is that the file ends up being 922 lines, which is longer than the original example case we looked at.
Example 4: Components in Separate Files
The fourth and final example 04-one-component-per-file-small
takes each component and puts it into its own file. The components are located in a separate directory and are exported individually:
Most of these files are between 50 to 100 lines, with only the Header
being around 243 lines, which is still relatively maintainable.
The downside is that we have many small exported components, and if we're exporting a component, it implies that it should be reusable. However, most of these components shouldn't necessarily be reused.
On the plus side, since the components directory is still in the main route, it's clear that the components are intended to be used only by this route and its descendant routes.
Deciding on Component Organization Rules
When deciding on your team's rules for how many components to have per file and whether to export them or keep them private, it's important to also consider the ideal maximum line count for your components. These two factors are closely related.
You'll likely encounter this decision early in your application development, especially when building out the app shell, header, footer, and navigation components. How you structure these components in the file system and files will set the standard for the entire app going forward.