Which component should get state in React?

When coming to React from an opinionated MVC framework (👋 Rails), understanding how we manage state in the different parts of our system can be confusing.

The boundaries for each function and component seem to lie in different places to MVC. There doesn’t appear to be a good mapping of the concepts to using React, particularly when coupled with Flux for managing the flow of data in our system.

You fear that the responsibilities for managing state are going to get spread across multiple functions or components. And the thought of making a change with a system like that is scary. You ask yourself “How much of the system will I need to know to make a simple change?”

With all software development we operate on the idea that for any change we want to make to a system, the surface area of existing things we need to touch should be minimised. This reduces the amount of knowledge required about the whole system to change one part of it. Also, it allows us to be more confident about our change because the impact to the rest of the system is limited too.

At its most simple, a system built in React is composed of functions that either get state or functions that consume state.

Following this idea leads to a simpler mental model for us and also code that is easier to understand in small pieces.

Let’s take an example from a recent codebase I worked on.

We’re rendering a card style view in a React Native app and we’re applying a background gradient that is randomly selected from a list of predefined colour pairs.

The discussion within the team was about the ‘proper’ place for calculating a gradient colour pair.

One of the objections we discussed was that the choosing the colour was a concern of the view. This turned out to be a pivotal moment for this particular feature.

It was here that we left behind MVC and arrived at the heuristic that a function is either building state or displaying it. And it has really helped with understanding throughout the team.

The problem with calling a function that selects the colours at random within this function is that it is no longer deterministic. And losing the deterministic nature means we miss out on one of the major benefits of React, a predictable description of how the state is displayed.

Here’s how we addressed this…

We pulled the responsibility of selecting a colour out of the component to allow it to be a pure function. And now we can easily make changes to the way we select a colour without impacting the way we display it.

In terms of readability and maintainability, this was a win for us.

On the surface it looks like we’ve made a superficial change to move the code from one file to the other. At the level of understanding the component and being able to modify or extend it in the future, we have made our lives a little easier.

So now, our approach to deciding on where certain functions belong begins with this question… Is this function/component building state or displaying state?