January 26, 2019
The “Five Point System” is a way to organize explicit work towards refactoring React code into best practices. While all new work should already be up to snuff, sometimes you need to create tickets that tell developers how to get the existing code into a good place. This is a good place to start. Investment in best practices requires more initial investment, but the result will have less bugs and be more future-proof. Over time, this will result in higher and more consistent throughput, and higher developer satisfaction.
The Five-Point System is a set of steps that you can use to direct much of the work that goes into component creation.
Lots of small components is better than a few larger components.
Each component being one level of depth is ideal, because it makes a shallow snapshot an effective test.
Not every component needs to be exported, but it makes testing easier; not every component needs its own file, but it makes separation of concerns easier.
See Container/Presentation Separation.
If your component has any non-presentational logic, create a container to wrap the presentational component, regardless of if it connects to state.
It’s best if you create a folder and separate file, but putting both in the same file is fine.
Use compose
to create to wrap the container. Use as many layers as necessary — Recompose layers add negligible overhead, and multiple layers allow for good separation of concerns.
const enhance = compose(
branch(shouldDisplay),
withHandlers(handlers),
pure,
...,
);
How do we accomplish this?
EXTRACT ‘TIL YOU DROP
Extract functions until you can’t anymore.
“The first rule of functions is that they should be small. The second rule of functions is that they should be smaller than that.”
How do you know your function does only one thing?
Connect to components at the lowest level possible, using whatever state management system you’ve got. In general, connected props should be used immediately in that component and not passed down. While base React works fine with prop-drilling, this is highly susceptible to bugs and ties you to your implementation. Usage of a system to pass data around is highly encouraged.
Connected props should typically be primitives (ie. not an object or array). There are occasional exceptions (particularly arrays of IDs), but they should be rare. The point of this is to avoid unnecessary rerenders due to unrelated data.
Particularly when we’re writing new features, it’s important to write good tests and get good test coverage. As the author of a new feature, you’re in the best position anyone ever will be to keep that feature stable! Branch coverage on your new files should be at least 80%, and you should aim for 100% at all times (it’s not as unrealistic as it sounds!).
If you write your tests before you refactor your work, you’ll both work faster (counterintuitively) and have higher confidence in your work. See Test-Driven Development for more.