Stateless Components with React

Rajdeep Kambo
Aug 31, 2018 · 5 min read

Introduction

As Web frameworks evolve, more layers of complexity are starting to develop — especially when it comes to managing state. As the creators of Redux put it:

“If a model can update another model, then a view can update a model, which updates another model, and this, in turn, might cause another view to update. At some point, you no longer understand what happens in your app as you have lost control over the when, why, and how of its state.”

At Hootsuite, React has become an integral part our front-end stack, and we’ve recently moved towards using Redux for managing the state of our front-end. Redux is built upon the Flux pattern. Flux emphasizes application state being abstracted into stores, and unidirectional data flow through an application. Unidirectional data flow discourages mutation of state, while encouraging individual components to subscribe to state changes from a store. This separation of concerns allows components to purely act as views — that render based the data provided.

Stateful Components

Prior to the introduction of Redux, a significant portion of components written at Hootsuite were stateful. This meant they didn’t rely on external stores, and had to manage their own state. While these components may be easier to write (since they don’t require initializing a store and defining store actions) they carry some added complexity. Namely:

  • Rendering: The components re-render whenever the state or the props change
  • Coupled Concerns: The components aren’t just views — they directly host the structure and logic related to updating the state
  • Javascript Classes: The components will require using classes in Javascript — a point of contention in the Javascript community (overblown or not, retrofitting a prototype based inheritance model to be more “object oriented” can be difficult to reason about)

To demonstrate the differences, I’ve implemented the same component as stateful, and stateless (with an external store). This component consists of a button and some inline text. Clicking on the button changes the color of the inline text. The state in this particular component is the color of the text.

Beginning with the stateful implementation, we define a changeColorState function which must be bound to the component itself:

Moreover, we define a helper function (also bound to the component itself) that reads the state directly, and return results accordingly:

In totality, the stateful implementation of the component ends up as:

Stateless Components

Although the stateful implementation isn’t long, the code is tightly coupled. The functions that manipulate and read the state are bound to the component itself. This is easily observed by the frequent use of the this keyword, which itself can be difficult to reason about.

In comparison, the stateless implementation will store state in an external Redux store. The component itself is stateless since it will purely act as a view.

As previously mentioned, there is an overhead incurred for setting up a Redux store. We begin with defining the initial state of the store:

Next, we define a Redux action for updating the store. An action is simply a Javascript object that sends data to a store. Actions contain a type as well as a payload — representing the data you want to update the store with:

Moreover, we define a Redux reducer. A reducer takes in the aforementioned Redux action, and returns the new state. Note that Redux emphasizes that reducers should be pure functions — meaning an entirely new object (that is a function of the old state, and the current action) should be created:

Lastly, we use createStore to initialize the Redux store. In order to create a store we need to pass in the reducer defined above, in conjunction to the initial state. As well, we create a function changeColorState which couples business logic (determining which color is next), and dispatches a CHANGE_COLOR action to the store. As per Redux’s dataflow paradigm, calling changeColorState passes the Redux action produced by changeColor into the changeColorReducer which then updates the state of the store:

All together, the code used for initializing the store ends up as such:

Now that we’ve defined a store, and functions to manipulate the store, we can simplify our component code:

The above helper function displayColorMessage doesn’t manipulate or read directly from the store. It’s a pure function that avoids mutation, and returns results based on its parameters. As well, the need for Javascript classes is nullified as everything is just a function (e.g. the StatelessComponentWrapper is a function of the props that are passed in).

In order to connect the StatelessComponentWrapper to the defined store, a mapStateToProps function is used. The mapStateToProps function defines which parts of the store the StatelessComponentWrapper component wants to subscribe to. In this case, StatelessComponentWrapper subscribes to any changes in color being passed in as props. Since React components re-render whenever the provided props change, any time color changes the StatelessComponentWrapper component will re-render.

Conclusion

Although stateful components are oftentimes easier to write, stateless components offer a number of benefits including:

  • Rendering: The components only re-render whenever the props change
  • Separation of Concerns: The business logic related to managing state is abstracted away, leaving the components to purely act as views
  • Unbounded Functions: Using the this keyword is no longer necessary because we’re no longer bound to a specific instance of the component. This leads to code that is much easier to read (and consequently reason about)

Full running versions of the stateful and stateless component examples are available here, and here.


Rajdeep Kambo is a co-op Student on the Plan and Create team at Hootsuite. He is currently studying Computer Engineering at The University of British Columbia.

Hootsuite Engineering

Hootsuite's Engineering Blog

Rajdeep Kambo

Written by

Hootsuite Engineering

Hootsuite's Engineering Blog

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade