Mark Erikson joins me to talk about state management in React. More especifically covering why Redux toolkit is such a great alternative to other libraries and the type of problems it solves.
We also get some insight into the origin of the current bad rep of Redux.
Get in touch with Mark:
Don't forget to leave a review of the episode or the entire podcast on Podchasers!
Meet our host, OpenReplay:
OpenReplay is an open-source session replay suite, built for developers and self-hosted for full control over your customer data. If you're looking for a way to understand how your users interact with your application, check out OpenReplay.
Context is like a dependency injection system. You put some value in at the top. It comes out at the bottom. It doesn't offer a way to update or store anything by itself.Fernando Doglio:
Awesome. Interesting. All right. Uh, Today, we're going to be talking about, well, essentially Redux and Redux toolkit, but you know, let's put it this way. I want to hear it from the source. I've been reading a lot about state management lately, and I've been reading the opinion of many people, but I know you have a very strong one in regards of Redux and Redux toolkit, so I want to, I want to know what you think. Uh, but before we get to that, I want to intro into it. So, uh, can we start at this at the beginning. Can you. Guide us through how you see state for a react application. What is it?Mark Erikson:
Yeah, so I would say. State is it's it's data. It's it's what's going on inside your application. Um, like it's, it's literally the variables and the pieces of information that you're dealing with and we can, we can slice and dice and describe state in, in several different ways. One, one thing I've seen is there's, you know, for example, there's server state data that is like the source of truth is whatever is on the server right now. And we just kind of want to cash, fetch it and cash it on the client. And we want to try and keep the client and the server values in sync with each other, as you're using the app, uh, in the flip side of that would be like client only state. Which is data that is just inside the application as it's running inside the user's browser. So things like is the dropdown open, which item is currently selected. Um, And we could go into lots of other pieces like that. Uh, another, another kind of avenue that you could look at it is things like location, state, you know, when we're dealing with browsers, URLs are a very important piece of it. They, they help determine. Which piece of the UI we're looking at right now, we can pass values through query parameters. Um, so you can, you can divide, stay along kind of like several different axes or categories, but it's all different aspects of what data are we dealing with in the application right now and in the react ecosystem, especially we have this idea. Our UI is always based on the state in our application. And so we have a very strong emphasis on managing state as the way to actually manage the UI. In the end, if I want to show a modal, unlike the jQuery days, I don't do, you know,$.myModal.Show or something. I would do a set state and say mode like set is modal set, modal visible. True. And I update the data and then the UI gets updated in response. So like all applications have state, whether you consciously think about it or not, but we especially have a strong emphasis on that in the react ecosystem.Fernando Doglio:
Uh, interesting. Okay. And. That translates into so many alternatives, so many different ways of dealing with this data, as you mentioned it, but out of the libraries and options that we have react itself already provides kind of simple ways of dealing with this and, uh, through props and through useState and through the use of context providers. Are these tools good enough for any type of state management scenario, let's put it that way or are they lacking features that bigger or more complex applications would need?Mark Erikson:
Somewhere in the middle? So it is absolutely possible to build very, very complicated apps with only the tools that react itself provides for, for managing state. So really what react provides is the ability to track state on a per component basis, whether it be the classical, this dot set state function in a class component, or the use state and use reducer hooks and a function component. But there they're all really equivalently the same thing. There's a piece of state associated with a component instance, somewhere in the tree. And in react, Data flows through the tree in a top-down manner. So you have parent components, passing data as props to children, which can pass data as prompts to their children. Alternately, you can stick values into a context provider to make it accessible to an entire subtree of the application without explicitly passing it through every value, but either way, the it's a very hierarchical. Top down data flow and that's intentional, but there are limitations to what is built into react. And that's not to say that this is bad. It's just that reacts tools are designed in a very specific way. And there are times we need to build applications that don't exactly fit that approach. There are, there are lots of times when we have data that doesn't neatly fit that hierarchical top down data structure. Like my, my UI is shaped like a tree, but maybe my data is not. This also gets into a discussion that I keep bringing up over time, which is what is my application? Is my application, my UI components? Or is my application my data layer? And you see people building apps with both of these different conceptual approaches and they're both valid. But they lead you in very different directions towards how you architect the app. Like if I'm, if I'm focusing on things where my UI is my components, then I might be doing things where I want to make sure that every component has like, is totally responsible for all the data that it needs by itself. So that, for example, maybe I could test that one component and it already handles all the data fetching and it just works or I can move it around the tree and it does its own thing. Whereas if I approach things from like my data layer is the app. Now I might want to approach things as testing that I can modify my data and my in my state changes whether or not there's a UI attached to it. At all. So I do see kind of like this conceptual split in how people approach, designing their applications. And they're both valid, but this goes back to the point that it, like, if I'm taking the latter approach, then I probably am more focused on managing my data outside of react, because I want to, I want to focus on building the data layer, the state management layer by itself, separate from whatever UI I might have.Fernando Doglio:
Again, also somewhere in the middle. Uh, it's great that we have a bunch of options and there are a bunch of very good options in the react ecosystem. The strength and weakness of the react ecosystem has always been that there's no one single defined way to do most things. And so react developers have always gone out and invented new libraries and push the boundaries and come up with useful new tools. The bad news is that now you've got to pick between 50 different options for the same thing. Um, so it, it is true. We both a strength in a weakness.Fernando Doglio:
Yeah. All right. Let's find your ideal state management solution. I guess it might be. Exactly like Redux Toolkit, but I want to know if you managed to achieve that with RTK or, uh, are you still far away from the ideal set of features, the ideal logic behind it? How do you see the ideal state management solution?Mark Erikson:
I'm not sure if necessary to spend time thinking about what would be I deal per se. So let's, let's actually back up a bit like what is state management? And I do feel there, there is a lot of confusion over this term itself. Uh, so I think at one point I tried to define it. Like a state management tool is something that allows you to store a value. Update the value in the future and read the value or possibly get notified when the value changes. So, you know, the use state and use, reduce or hooks fulfill this because they let you read the current value by accessing the array. They let you call the setter or the dispatch function, update it. And you're notified it changes because the component is re rendering Redux fits this because it has a state of value inside. You can call it, get state, you dispatch an action, update it, and you can subscribe to know that an action was dispatched and calls get saved to see what a changed mob X fits this because you've got state in your, your observable classes and value. You can mutate the data to update it and mobX takes care of automatically applying the changes to whatever pieces of the code actually depend on that value. Uh, the piece of confusion that I repeatedly keep seeing, and I'm going to rant about this for just a couple seconds, is people keep saying that I'm managing state with context. And I'm nitpicking, but this really is a, a, a confusing point that people misunderstand context doesn't manage anything by itself. Context is like a dependency injection system. You put some value in at the top. It comes out at the bottom. It doesn't offer a way to update or store anything by itself. Your act like if you're dealing with state, you're actually managing it in a used state or use reducer and you just happened to be making it available via context, rather than passing it down by a props. I could have done the exact same thing by manually passing the data down as props all the way through. So part of the re one of the reasons why I think we have so many different state management tools in the react ecosystem is that there is no one single ideal way to manage everything. My, my favorite word as I've gotten deeper in my career is trade-offs nothing's perfect. Everything has pros and cons. Everything has trade-offs. So. Let's let's very briefly look at three common tools in the react ecosystem, so that all four, so react components, state it's built in. You don't need any additional libraries, but it is limited to the component tree. And by default, like you update state in the component, everything below that is going to start re rendering, uh, Redux it's outside the UI. It has the cool things like the dev tools and middleware. It does require work to set up a, it does require extra discipline and writing more code than it would have had in just the react component. Uh, but you get extra benefits, like being able to do to inspect the history of the state. Um, it also requires that you think in functional programming type terms, mob X is relatively simple to use. Conceptually, you create some classes or some plain objects, mark them as observable. You just mutate the fields and mob X takes care of passing along all the updates automatically. Um, It does kind of go against some of reacts conceptual principles as far as like immutability versus mutation, but in a lot of ways, it's also easier to use. Um, X state wants you to focus on defining data flows as explicit state machines, where you say here's the possible conditions that my system can be in. When a certain thing happens, it transitions from one state to another. And that allows you to do cool things like visualizing how the logic in your app fits together. So each of these tools has different trade-offs different purposes, different use cases. You can use them for a lot of the same things. But a lot of it depends on what specific problems you're trying to solve. And also just like what your preferences are. If I prefer a more functional programming oriented style, I might prefer Redux over mobX. If I prefer, you know, dealing with classes and mutation that I just kind of want stuff to happen automatically. I might go with mobX.Fernando Doglio:
Okay, so there is no ideal, no ideal solution. It's all preference. All right. So going into Redux now, I actually, yesterday I think I watch, uh, uh, um, a discussion you had with, uh, with someone, uh, on YouTube. And you were saying that. You're showing numbers in you, you're showing how, um, although people say that, uh, Redux uh, is dead or is dying, uh, it's actually quite the opposite. You show, you show charts and so on, and we're going to cover that in a bit, but, uh, other than the fact that that may or may not be happening, why do you think Redux has gotten so much such a big rep. Let's put it that way. Um, lately, is it because as you put it, you just put it, I mean, it covers all the, you know, it ticks all the boxes when it comes to what state management solution should be doing. So what is your take on that?Mark Erikson:
Like, like why have people gotten angry at Redux for years? It's been way. Th there's a lot of historical context that goes into this. So Redux came out in 2015 at the tail end of the year long period that I referred to as the flux wars, Facebook announced the concept of a flux architecture in 2014. And over the next year, dozens of different flux libraries came out in the ecosystem. And at first Redux was just another one of those flux libraries. And then it got really popular and killed off all the others. But that led to a scenario where people began to assume that if you were using react, you had to use Redux. And frankly, people began shoving Redux into a lot of apps that it never needed it in the first place. And that all that meant. You know, people began experiencing pain and suffering because they were using it in a way. It really wasn't intended to at all. And from there, you all, like you had people using Redux without understanding what purpose it was intended to solve in the first place. On top of that, the original Redux patterns shown in our docs for years were frankly, very verbose you've. You've heard the word boiler plate. Turn around a lot. And it was very justified. Like you had to write action type Constance and action creator functions, and lots of spreads and array maps, and concats and reducers for mutable updates and all this code, just to update a couple of fields in your, in your, in your state. And there's very good reasons for that. Like all these patterns had reasons to exist, but frankly, a lot of it was very painful to write. And it was very easy to make mistakes. And then you started to see overlap with tools that came out in the react ecosystem that overlapped with the way and the reasons people were using Redux. So early on reacts all contexts API did not work very well. And so people would use Redux just to avoid prop-drilling. Well, the new context API that came out in re react, 16.3 was specifically designed to solve that problem. So if the only reason you were using Redux was to avoid prop drilling well context already does that and it's simpler to use. People have always used redux to store hashed server state you know, data fetching your to do's and your users and in your comments and whatever else, you can totally do that. But out originally out of the box, Redux didn't provide anything for it. So you had to write all the code to do that yourself thunks and reducers and actions, and, you know, use effects and whatever. Data fetching and caching libraries like Apollo and react query were specifically designed to solve that use case. So again, like if the only thing that you were using Redux for was data fetching and cashing will, these tools are simpler in these reviews. So when we started to see the backlash against Redux in 2017 and 18, it was, it was fairly deserved. Like the shininess had worn off. People had started to see the pain points of using this tool. But especially when it was used in places where it didn't need to be used in the first place and new tools existed that solved some of the same use cases with less code.Fernando Doglio:
So my first caveat is I have not had a chance to actually try any of these other libraries, myself. Like I have far too many Redux related things that I don't have time to get to anyway, much less. Try out anything else in my classroom at this point. Um, it does kind of go back to my, my favorite word earlier. Trade-offs. You know, so, you know, these, these Atoms or these like multiple miniature stores in a lot of ways, they are probably simpler to use. You don't have to think about the men like the, the work of defining reducers. You don't have to think about defining actions. Dispatching them, um, like you, you've got like these little self-contained pieces of state, it may actually, in some ways be a little simpler to reuse that in a couple of different places across the app. Um, yeah, I'm, I'm definitely at the limits of, of what I actually know about the, the API APIs and how these things can be used. Um, the, some of the trade-offs are that. Maybe the process of where and how you update the data now gets kind of scattered through your different components. And so if you're trying to track down, like where does the data actually get used and updated? You might have to do more searching. Through the rest of the code base to like follow the imports, see where it gets it's referenced and used. Um, that's, that's not necessarily a bad, bad thing. Uh, it's just an observation that, you know, whereas with Redux, you, you know, to always look at the reducers, maybe with like a Jotai or recoil, you're now having to kind of like look at a bunch of different components. Differences in approach, not something that's inherently better or worse per se.Fernando Doglio:
All right. Fair enough. Okay. Now, final question. Let's address the geen elephant in the room. Redux isn't dead, or at least the toolkit isn't that he's not even dying. So how would you justify going with the toolkit. Let's forget about the old Redux. Let's just talk about the toolkit. How will you justify going to a, for the toolkit approach? If there are other, I don't want to say simpler, but, uh, seemingly more straightforward ways of dealing with state and always, always dealing, uh, or seeing, looking at it from the POV of a brand new project. Getting started on a project and deciding on a, on a, on a state management solution, not something that maybe it's been using Redux for like 10 years, not 10 years, but you know, if you got the point.Mark Erikson:
That would be impressive. Yeah. Um, so there there's, there's a few different arguments you could make. Um, one is simply the, the appeal to popularity. Redux is still by far the most popular state management tool, like separate from react itself for react apps. Uh, my, my estimates are that it's used by around 45 to 50%, uh, react apps. The pattern itself is well-known that we have very good documentation. There's a very good chance. You will run across an app that uses it at some point in your career. It is a very known quantity. It has a strengths and weaknesses, but it is a known thing. Like it's not like it's, you know, it's well maintained and supported. So one thing is that we it's the semi default option. And frankly, that is why some people pick it as far as technical merits. A lot, like a lot of the original arguments are still entirely valid. Like Redux was designed to make it easier to understand when, where, why and how your data is changing in your application and the ability to look at the action history log and see the sequence of updates that occurred, like even just reading the names of the actions that were dispatched can help to tell you this sequence of events occurred, the ability to look at the state at any point in time, the changes to the state after given action was dispatched. The dev tools have the ability to show you the stack trace of where the action was dispatched in the first place. These are valuable tools to understand how the app is actually behaving the technical architecture of being able to plug in middleware of your choice into the store. And. Choose your own approach for async logic for being able to do things like centralized logging or analytics, or, you know, other customer behavior is still a very powerful model that, you know, you, you don't get out of the box, like react state, um, with Redux toolkit specifically. We have solved all the problems of boiler plate and everything else, and the amount of code it takes to set up a store, write a reducer make some updates, dispatch, and action is really pretty minimal at this point. I mean, it's, it is still absolutely more lines of code than like a single use state in a component. Even compared to other solutions, it's not like it's actually that, you know, w like way more lines of code anymore. And Redux toolkit does have a lot of very powerful utilities built in for doing things like managing normalized state, um, you know, to, to update things in a lookup table. We also, last year we added a new capability to Redux tool kit called RTK query, which is a complete server state data fetching and caching solution. So you define a set of end points, whether they be rest or graph QL or just a generic async function, and you can describe the relations between them. So like when I, when I update this piece of data on the server, we should re fetch these items and it automatically generates a reducer and a middleware that manage all the caching and the lifetime process. And from there, it gives you a set of auto-generated react hooks. So you can just call, you know, use, get Pokemon query Pikachu and your component. And it does all the data fetching and the S the loading state and everything else out of the box. So like, even that, like, you can, you can actually use it without technically without defining a full Redux store by hand. There's a way to I just kinda like auto magically make one for you, but that makes using Redux for even kind of like per component data, fetching a very valid thing. Like why, why should I have to write a use state and the use effect and a fetch function when I can just get a, get a hook that does. So there are a bunch of valid technical reasons to argue in favor of using Redux toolkit today. At the same time, it's not the best choice for every application. There is there's bundle size, there's mental concepts, there's, you know, conceptual overhead, and it is entirely valid to choose a different tool because of the problem space that you're solving or the preferences of how your team wants to work with things. And that's all I really want. I want people to look at the problems they need to solve, discuss the trade-offs and the pros and cons of the tools in the space and pick a tool that best solves the constraints that your team is dealing with. Fernando Doglio: That's fair. So there's definitely a lot of space and for it. And, and what you're saying is essentially it's a very mature solution that, yeah, it's hard to, hard to compete with. Awesome now. So let's go quickly to the last three questions. We ask every one of our guests, not related to Redux, but to the IT industry in your experience in general. So what's the best advice you ever received in some ways I'd have to think about that a little bit, but I'm just going to pick a phrase off the top of my head. Right. Um, I had a very good mentor during the first couple of years of my career, and it's not necessarily advice per se, but like the first thing that pops into my mind is he would say. We can make it do anything. It's just software. Um, like being a programmer is great. We get to build stuff from scratch. Like this thing did not exist. And now it does. And you know, you could, you could sort of take this as advice and apply it to a lot of different areas. Like we can make this program, do whatever it needs to do. It may take a lot of time. It may be really hard. Like it's, it's just code. We can think about it. We can build the thing, like it's possible.Fernando Doglio:
Absolutely. As long as you have enough resources and time, that's that, that's what I, I like to say about, yeah. I absolutely agree with that. Um, what's it most excited project you to worked for?Mark Erikson:
Nice. Is that still available somewhere?Mark Erikson:
An internal proprietary company tool.Fernando Doglio:
Yeah. Fair enough. Alright. Uh, last one. Uh, what is one thing you wish you knew before you started.Mark Erikson:
How to think through debugging, uh, debugging is something that unfortunately we do not actually teach as an industry. Um, I mean, there there's a lot of stuff. We don't do a good job of teaching as an industry, but. There are, there are a lot of basic principles of debugging that you can, like you can think through it's the scientific process, like understand how the code is supposed to be working, make an informed guess or hypothesis about here's the behavior I'm seeing. I think it's doing this, go through the code and inspect it and, you know, either confirm or disprove. Your understanding and repeat. And we don't teach people to think about how to debug. We don't teach people how to use the tools that are available to debug. Um, whether it be. Print debugging or your actual, you know, step in, step out, break points, step to buggers or cheap plug for my day job, the replay time traveling debugger like legitimately, this is a thing that people can get better at, and nobody gets told how to do this when they start working. So we all learn this the hard way over the course of our careers.Fernando Doglio:
True. Absolutely. Yeah. I use console log for too many years before I started actuallyMark Erikson:
Print debuggers and stepped debuggers are both viable.Fernando Doglio:
Yeah, absolutely. All right. That's it. That's all the time we had way more than they were then when we had, um, can you tell people where they can find you? And if you have, if you want to plug your project again, go ahead.Mark Erikson:
Uh, I'm, I'm@acemarke on Twitter and Reddit and react to flux. I'm at mark Ericsson on GitHub and stack overflow. Uh, I generally hang out in the reactor flux discord on a, on a nightly basis and spend way too much time on Twitter. Um, What am I even working on right now doing my day job at replay Redux is in a good place. We just shipped react, Redux version eight, um, Redux toolkit 1.8. I've got a lot of stuff I need to work on. I just don't have the list of it off the top of my head right now.Fernando Doglio:
That's all right, that's it. Thank you again, mark, for agreeing to come in and discuss. Uh, with us and the rest of you. Yep, absolutely. And the rest of you, that's it. Catch you on the next one?