When (and when not) to reach for Redux
trust me, I maintain the library
This is a fancified excerpt from Mark Erikson on JS Party #146. Mark maintains Redux & Redux Toolkit and has been lovingly called, “Tech Support for the React Community”. To get the full experience you should listen while you read.
🎧 Click here to listen along while you read. It's better! 🎧
I am a huge proponent of a couple of specific ideas. One is that you should always try to understand what problems a specific tool is trying to solve, and part of that is…
“What is the time and the context and the reason why this tool was even invented in the first place?”
And another is that you need to understand exactly what problems you are trying to solve in your own application right now, and pick the tools that solve your problem best. not because someone else said you should use them, not because they’re popular, but because this is what works best for me in this particular situation.
Redux and React Context then
So in the case of Redux, it 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.
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.
Now, it also happens that because Redux used the old-style React Context API from its beginning, using Redux in a React app also happened to somewhat 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, which is a royal pain.
So using Redux with React to let people side-step that issue… that is a reason why many people picked Redux in ’15, ’16, ’17.
Redux and React Context now
Well, with React 16.3, React came out with 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, where you say “Here is a value”, and any portion of that component subtree can ask to read the value. That’s literally all it does.
So if the only thing you needed to do with Redux is avoid passing data as props through 15 levels of your components - well, that’s literally what Context was invented to do.
So, if that’s all you need, then you don’t need to add Redux just to add that capability; use Context instead.
Now, I’ll go off on a specific point here. I am constantly seeing people compare
“Should I use Context or should I use Redux?”
And they seem to think that Context itself is a state management system. It’s not.
It’s a dependency injection mechanism, and you can put whatever value you want in Context, and 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 yeah, useReducer
plus useContext
together kind of make up a state management system. And that one is more equivalent to what Redux does with React, but Context by itself is not a state management system.
Redux and other tools
On the flipside, almost everyone is needing to cache some server state in their apps.
“Let’s go fetch some data on our users, on our posts, on our comments, and then display them.”
And traditionally, that’s been done by REST APIs and whatnot… But these days we have GraphQL. And while not everyone is using GraphQL, a lot of people are.
And while GraphQL by itself is just a data transfer protocol…
“Here’s how I format my request, here’s how I format my response.”
The assumption is you’re probably using a sophisticated client like Apollo Client to manage that data. And Apollo Client has a lot of features built in, like handling a normalized cache of all the data, and if I ask for the same thing, it’s already there. And it gives you this nice little interface where it’s just like: “use query” and it gives you back: “data is loading error” in your components, so you can decide what to render.
Similarly, if the only thing you were doing with Redux was storing cache data from the server, and you choose to use GraphQL and you choose to use Apollo Client, then you’ve just fulfilled the use case that you were previously choosing to use Redux for, and for that situation you don’t need Redux.
Similarly, there’s a couple new libraries –swr and React Query– which do the same kind of thing, but focused around more of a REST API.
It’s just “Here’s my URL, fetch it, give me back “data is loading error” and they cache the stuff officially and can share it some. And again, if that’s the only thing you were doing with Redux and you choose these other tools, then they replace that use case and you don’t really need Redux at that point.
On the other hand, while you can do some limited bits of client state management with Apollo or maybe with React Query, that’s really not the use cases they were meant for.
How to think about Redux
So the way I would distinguish it is: Redux is a very generic state management tool that can be used for a broad array of use cases.
- Caching state from a server
- UI state
- other complex data management on the client
But it’s probably not going to be the best or most efficient tool at any of those use cases. Other tools like React Query or Apollo are much more specialized for this specific case of data fetching.
So you can do many things with Redux. It might not be quite the best at all of them, but you can do lots of different things.
You can do server caching with Apollo and React Query, they’re gonna be very good at those, but you can’t do some of these other things. So it’s really a question of:
- What specific problems are you trying to solve?
- What problems do these tools solve?
- Where’s the overlap between those?
Mark has also written about this subject in the past. Our excellent conversation with Mark doesn’t stop there. Listen to the entire episode for much more on the world of React and Redux. You can play it from the start right here 👇
Oh, and don’t forget to subscribe to JS Party in your favorite podcast app so you don’t miss future episodes and insights. ✌️
Discussion
Sign in or Join to comment or subscribe