architect-handbook

Software Architect Handbook

View on GitHub

When and when not to reach out for Redux

Resources used:

Redux origins

Redux was invented as an implementation of the Flux architecture), which was in turn created to deal with limitations people had found in event-trigger-based state management, like Backbone specifically.

As requirements for JS single-page applications have become increasingly complicated, our code must manage more state than ever before.

So I set user.firstName, it triggers a “change firstName” event, some other code is listening to that, it triggers another event…

Next thing you know, you’re 15 events down one big synchronous call stack, and you have no idea why this happened in the first place. That’s what Flux was invented to solve, and Redux basically perfected that particular approach. And that was the problem people were trying to solve in 2015.

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. When a system is opaque and non-deterministic, it’s hard to reproduce bugs or add new features.

Now, it also happens that because Redux used the old-style React Context API from its beginning, using Redux in a React app also accidentally solve another common problem, which is that many different parts of my app need to use the same state at the same time, and I would normally have to lift that state up maybe all the way to the root app component in order for many components to share the data. But if I do that, I would then have to prop-drill and pass that data as props through every level of the component tree.

We’re mixing two concepts: mutation and asynchronicity.

Following in the steps of Flux, CQRS, and Event Sourcing, Redux attempts to make state mutations predictable by imposing certain restrictions on how and when updates can happen (three principles of Redux).

Redux vs Context Now

With React 16.3, it came a new, improved Context API, which unlike the old one, was recommended for production usage from the day it came out. And the only purpose of Context is to act as a dependency injection mechanism scoped to some portion of your subtree.

So if the only thing you need to do with Redux is avoid passing data as props through 15 levels of your components, that’s literally what Context was invented to do.

Context is not a state management system but a dependency injection mechanism. Most often you are the one managing that state in a React Component, with the useState hook or the useReducer hook. And you’re the one deciding where the state lives, handling how to update it, and then putting the value into Context for distribution.

So, useReducer plus useContext together kind of make up a state management system more equivalent to what Redux does with React.

Redux Use Cases Now

But it’s probably not going to be the best or most efficient tool at any of those use cases. It might not be quite the best at all of them, but you can do lots of different things.

Redux Tradeoffs

None of these limitations are required to build an app, with or without React. In fact these are pretty strong constraints, and you should think carefully before adopting them even in parts of your app.

These limitations help build apps that:

Ask yourself