Joel and Mark Erikson chat about the motivation behind Redux. The historical context and the future of Redux. How Redux Toolkit solves community pain points. Additionally, Mark Erikson gives a walkthrough of how Redux Toolkit works and how to use createSlice, createAsyncThunk, and createEntityAdapter.
Immer - a library created based on the “copy-on-write” mechanism — a technique used to implement a copy operation in on modifiable resources.
Redux Toolkit - an add-on package to Redux, which includes opinionated defaults.
This blog post was a result of responding to the endless waves of “Redux is dead...”
People don’t understand the context and history behind why a particular tool exists—for example, jQuery, Angular, Backbone, etc.
All these tools were created at a specific time, in a particular place, by people trying to solve particular problems.
Example of this: "Things You Should Never Do, Part I" by Joel Spolsky.
“When you throw away code and start from scratch, you are throwing away all that knowledge. All those collected bug fixes. Years of programming work.”
Docs: “The basic idea is that you will apply all your changes to a temporary draftState, which is a proxy of the currentState. Once all your mutations are completed, Immer will produce the nextState based on the mutations to the draft state.”
During Gatsby’s bootstrap & build phases, the state is stored and manipulated using the Redux library. The fundamental purpose of using Redux in Gatsby’s internals is to centralize all of the state logic.
useMutableSource for compatibility purposes.
useMutableSource - enables React components to safely and efficiently read from an unreliable external source in Concurrent Mode. The API will detect mutations that occur during render to avoid tearing, and it will automatically schedule updates when the source is mutated.
The recommended way to start new apps with React and Redux Toolkit is by using the official Redux+JS template for Create React App.
The first problem that it’s trying to solve: it takes too many steps to set up a store.
The solution is to create Reducers that specify how the application’s state changes in response to actions sent to the store.
Actions only describe what happened but don’t explain how the application’s state changes.
One key/value section of that object is a “slice,” We use the term “slice reducer” to describe the reducer function responsible for updating that slice of the state.
createSlice creates your actions and your reducer for you, you don’t have to worry about type safety here. Action types can just be provided inline.
thunk before the payload creator is called, you may provide a condition callback as an option after the payload creator.
@ngrx/entity library created by the NgRx maintainers and significantly modified for Redux Toolkit.
actions to pass. And the CRUD methods may be used in multiple ways.
"Redux is not designed to be the most performant or the most concise way of writing mutations. Its focus is on making the code predictable."
Tradeoffs of React Hooks:
Recap: It's about tradeoffs.
Neither approach is "right" or "wrong" - it's about what tradeoffs you want to make: - How much do you want to "separate concerns"? - Do you prefer "shallow" testing of components, or fully "mounting/integrating" them? - How important are shallow component trees and static typing?
Joel Hooks: [0:00] I really want to talk about Redux. I'm excited about it. I was a big fan out of the gate. Then, when he first posted it, I was like, "That's it. We got him to make the Egghead course." I don't even know how many people have gone through that thing.
Mark Erikson: [0:17] Gazillions.
Joel: [0:17] Yeah, a lot. For a long time, we had to literally change our popularity algorithm, because it would not stop. It would not stop being at the top. It's like, "We really got..." We had to add it, and age component kind of fade away.
[0:32] At that time, nobody thought about this. You could just always put all our data up here. Data flows down, so we put it in our global store. Everybody just had this revelation. Then, over the last few years, I've seen it. It's interesting that they get. I can see trends, right?
[0:53] Based on our courses, I get to see what the zeitgeist is favoring at the moment, which ebbs and flows. At the same time, I also use Reddit a lot. I'm a redditor. I'm anonymous on there. I have my 13-year-old throwaway account. There's no way I'm going to reveal online, but I see you. I see you in the forums. Literally, every time Redux pops up, there you are.
Mark: [1:18] Pretty much. I've got a TweetDeck column set up for mentions of #redux on Twitter. The rest of it is me just being stupid obsessive about refreshing social media about every five minutes, which is probably not a great thing.
Joel: [1:40] Honestly, I appreciate your input. Frankly, I feel like people are crapping on Redux and throwing the baby out with the bathwater. You're kind of a reasoned voice, and you're like, "Here's why it's still good." It's not like you're telling people that they need to use Redux or that's their only solution, that there's not other solutions out there.
[1:58] It's like, "Here it is. Here's why it's still good." Why are you still excited about Redux, and why do you keep carrying the torch for this library?
Mark: [2:08] You want me to go into the whole thing, right?
Joel: [2:11] I'd love it. Yeah. I have a list of questions too, so if we get a tangent, that's fine too.
Mark: [2:19] There's a whole bunch of reasons. Part of it is having accidentally gotten myself into to the position where I am the primary maintainer, I feel a huge sense of responsibility to the community. In some ways, that's increased by the fact that there are so many negative voices talking about Redux at this point.
[2:49] You know the story of "The Little Red Hen"? The kids' story where, "I'm going to bake some bread today. Well, I'm going to have to cut down the wheat. Who's going to help me? Nobody. Nobody. Nobody. OK, I'll do it myself. Who's going to help me prepare the flour? Nobody. Nobody. Well, I'll do it myself." I feel a certain sense of that in a lot of ways.
Joel: [3:21] You think it's a sense of responsibility at this point. You picked up the torch, and you haven't had a particularly good reason to drop it either, I would assume. There has to be some measure of enjoyment out of it for you too. You're getting value out of it in terms of your experience and the community involved, I would assume.
Mark: [3:39] Absolutely. If I look back to before I got involved with Redux in the open source community, I spent most of my free time playing games and goofing off. I still do some amount of that. The majority of my free time goes to Redux related stuff. Beyond the sense of responsibility, it gives me something to do, to keep me occupied outside of work.
[4:03] I have gotten a lot out of it personally, as well. I've been able to use a lot of my React and Redux experience at my day job in various forms. I've had the opportunity to go speak at conferences, which is something I certainly would never have had the chance to do otherwise.
[4:23] I've amassed some measure of Internet popularity among a very small segment of the Web programmer community for all that's could be getting me. Obviously, I'm not doing it for the virtual Internet popularity points. I'm doing it because people are using Redux, have been using Redux, and will continue to be using Redux to build applications, and I'm trying to make their lives easier.
Joel: [5:00] I'm interested in that because one, maybe you get into why do people -- not oppose, isn't the right word -- but how do people criticize Redux in general? What are the big ones that the people throw out their effort?
Mark: [5:16] There's a lot of them. A lot of them are rather justified. I'll specifically highlight two different posts that I wrote. Almost exactly two years ago I wrote a post called "Redux Not Dead Yet."
[5:38] It was a deliberately click-baity title for two reasons. One is that I was about to go teach a Redux workshop because Ryan Florence at the time was trying to do a little workshop-teaching startup called Workshop.me. I was about to go do my first one, which turned out to be my only one as it turned out.
[6:05] At the bottom of it, yes, I did a little sales pitch for, "I'm about to go teach this workshop. You should go sign up," etc., etc. I was trying to get it in front of eyeballs. At the same time, I was legitimately trained to respond to these seemingly endless waves of, "Redux is dead. Redux is awful. Redux has been replaced by fill in name of tool here."
[6:33] There's a lot of stuff that goes into this. Part of it is that people don't seem to understand the context and history behind why different tools exist. If you go back and look at jQuery, Angular, Backbone, or even older stuff like Windows Forms or something, all these tools were created at a certain time in a certain place by people trying to solve specific problems.
[7:05] They were written using knowledge that existed at the time and inspired by other tools and solutions at the time. Understanding the context and the reasons why a thing was created in the first place help you understand where it fits into the larger picture. If we look...
Joel: [7:29] I like to sometimes think of this like, if you take that at scale, there's all sorts of scales of that particular situation. Sometimes you're scrolling through a piece of code. You'll run into an if block. You're like, "That is there for a reason." Nobody's randomly going through and dropping if blocks in there. That's there for a particular reason. There's context.
[7:52] There's a story behind this block of code. You take that out to the library or the particular tool and out to a whole ecosystem, design pattern, or J2EE or whatever. You're talking hibernate ORM style. This exists for a reason because we need a solution at the time.
Mark: [8:11] If you go back to around 2000 or so, there's a guy named Joel Spolsky, who eventually went on to help found Stack Overflow.
Joel: [8:20] This traces back all the way to Joel Spolsky.
Mark: [8:22] Fog Creek. He wrote a specific post where he was talking about why you should never rewrite your application. At the time he was saying it in the context of Mozilla throwing away their original code base and becoming Firefox and then whatnot down the line.
[8:40] His argument was that, "Yeah, your code base is ugly because your code base has fixed lots and lots of bugs and solved business cases. All those special cases and stuff that you have in there are solving problems." When you go throw away a code base, you're losing that knowledge and having to reconstruct it.
[9:03] It's entirely possible that some of the problems that code was trying to solve are no longer valid. Maybe you ought to rethink things, but there are reasons why that exists. If we swing that back around to the Redux side of things, Redux came out in 2015. It was basically trying to do two things. It was in a lot of ways a conference demo that grew way bigger than anyone ever thought it would.
Joel: [9:29] Prototype gone wild is the...
Mark: [9:31] Yup. It was also intended to be just another Flux library implementation. 2013, Facebook announces React. 2014, Facebook announces this Flux architecture, but it was more of a pattern than a specific tool. Over the course of 2014 and '15, dozens of competing Flux libraries came out mostly with names that were bad puns on "Back to the Future."
[10:03] Everybody had their own variations on how this Flux architecture thing was supposed to work. Redux was originally just another variation on that, with the goal of being able to do some hot reloading and time travel.
[10:20] You have people asking, "Well, why do I have to dispatch things? Why are they called actions? Why do I have to have all this separation between my UI and my data management? Why do I have to put it all in one place?"
[10:42] You can trace all of those things directly back to the inspirations for Redux at the time it was created. It was a Flux architecture implementation. The term action comes directly from the Flux documentation.
[11:00] The idea was rather than having multiple independent stores that somehow need to synchronize between themselves in case there's dependencies, you put all that logic in one function, and you don't have to worry about synchronization anymore.
[11:17] There's entirely good reasons why these things exist, but people who are coming into Redux today don't see the context behind that. They just see these patterns. They don't understand the reason for the patterns.
[11:35] Some of the other criticisms that show up, verbosity. Why do I have to write const addTodo = "addTodo"? Why do I have to have deeply nested spread operators in my reducers? Why do I have to have an action object, an action type, an action creator, a mapDispatch, and all this other stuff?
Joel: [11:59] Fundamentally, the reality is you don't need much of any of that. You don't have to have it.
Mark: [12:04] Exactly. These are common patterns.
Joel: [12:07] It's what people saw. It was how the examples were presented. It's how people learned it, the blog posts were written, applications were architected, and then there we are.
Mark: [12:19] That is a lot of it. You don't have to write action types as constants. The goal is prevent a typo. In case I misspell addTodo in one place or the other. Type strings don't have to be all uppercase, but that's a common convention for indicating that something is a constant, etc. Again, there's perfectly valid reasons why these patterns exist.
Joel: [12:49] That trace back decades, too. Constants as capital letters, I first saw that probably in Java or whatever 15 years ago when I was introduced to that. Here it is today. It's like, it's just separation, it's visual, and it exists for a reason. Now people are demanding why. Why do we have to do this?
Mark: [13:09] Some of the other things that pop up, data fetching patterns. Why do I need to dispatch a start action, and then a success and a fail? You might want to keep track of if you're loading the data, show a spinner. If the call succeeds, of course, you have to do something with the data. If it fails, you still might want to clear out the spinner, etc.
[13:36] Trying to handle all cases validly. Could you get away with just the loaded data? Sure, but it's trained to set yourself up for proper architectural patterns.
[13:52] Where this starts to get confusing in today's world is that there are a lot of other excellent options for managing state and solving problems in the React ecosystem. There's MobX, there's GraphQL and Apollo.
Joel: [14:10] React itself. Now we have useReducer, which is like mini Redux. Not really, but it is. We get some of that same flavor and context is not a forbidden fruit anymore. React feels like it's allowing us to do more. Particularly in the localState, feels way cleaner than it was at Redux time.
[14:32] To me, that was part of the problem, too. It was like, "We have Redux." Now everything is Redux.
Mark: [14:38] There were, again, reasons why that happened. If you look at the docs, the Three Principles page says that you should have a single source of truth. That has been very understandably over interpreted. The docs weren't trying to say you literally put everything into Redux. That is a very understandable way to read that phrasing.
Joel: [15:06] Especially if Dan Abramov writes that.
Mark: [15:10] I've got a section in the FAQ page that tries to give some rules of thumb for when it makes sense to put something into Redux versus when it makes sense to keep it in component state. I'm going to have to try to emphasize that more as I'm working on rewriting the docs.
[15:28] The combination of that phrasing, the single store, and wanting to have things show up in the DevTools. A lot of people have assumed that they must put literally everything into Redux. Quite frankly, that is overkill and leads you to write a lot more code than you would want to have to deal with.
Joel: [15:56] Exacerbating that boilerplate problem that people are [inaudible] .
Mark: [16:00] If you're dispatching actions on every keystroke in every form, it's way too much time and effort.
Joel: [16:10] That makes sense. You've addressed this. It's gone on. You've seen people putting forth these arguments. It's gone from, "Hey, you might want to reconsider Redux," to none of that. Then at the same time, I'm watching what you're doing. I'm interested, because you're addressing these complaints.
[16:36] One, you're seeing the pain that people are talking about, and you're there listening to the community, obviously. Not only are you defending Redux, but you're actively trying to improve the areas. Most recently, Redux Toolkit is probably the big one. Then continuing development on the DevTools, which are still really cool and useful. The Toolkit's probably the big leap forward, if I'm reading it correctly.
Mark: [17:03] When I got involved with Redux in the first place, one of the things I did early on was I started collecting links to all the different Redux-related libraries that I was seeing pop up on GitHub. I started seeing a lot of similar types of libraries popping up.
[17:22] A lot of them were, for example, generating action types and action creators and reducers to handle different kinds of cases for you automatically, so you don't have to write them by hand.
[17:36] It got to a point where I ended up filing an issue for discussion saying, "OK, I'm seeing the same complaints pop up." Boilerplate and writing too much stuff by hand. What can we do officially to try to provide something that would simplify things for users?
[17:58] That ended up with an issue that was, I don't know, 200 comments long. Eventually it devolved into people just pasting links to their own libraries, and it sat there for a while.
[18:08] In I don't know if it was maybe early 2018, somewhere there, had a couple of specific discussions on GitHub and Reactor Flux that inspired me to go back to that issue and try to do something about it.
[18:30] A guy named Justin Falcone, I can never remember how to pronounce his last name, had specifically suggested in the first comment to that issue that a minimum viable solution would be an official package that bundles in Redux Thunk and simplifies creating a store and provides something to help create actions and reducers.
[18:57] I ended up whipping something in two or three evenings and putting it up for some discussion. It took off from there. It ended up having to sit for a while, because I had to go off to do a lot of stuff with React Redux, especially around version 7 and our Hooks API and everything.
[19:17] The other key thing that happened was Michel Weststrate, the guy who created MobX, who is an absolute genius, by the way, came out with this library called Inmer, which drastically simplifies writing update immutable update logic so you don't have to write nested spread operators.
Joel: [19:36] Before that it was Immutable.js or whatever which was clunky and huge and all that stuff. Inmer comes on, Michel brings that to the scene. It changed a lot of apps.
Mark: [19:45] Oh, yeah. Putting all these pieces together really changed things. Once I had time to turn my attention to try and to both finish out the APIs, based on the use cases and the community solutions and the request that I was seeing. Then try to start publicizing it over time and get people aware that this is an actual thing that exists, and I would please like you to take a look and use it.
[20:20] It has taken off amazingly well. Especially, because it was originally named Redux Starter Kit, because we'd managed to get the npm package name handed to us.
[20:34] The problem was we were seeing a lot of people think that it was a cloneable, boilerplate repo or something that was only good for beginners or something, when it's supposed to be meant to be helpful to all Redux users of any experience level, at any point in a project.
Joel: [20:55] The full lifecycle of an app too. You'd start your app this way and then want to add something new, a Rails generator would be my closest analog. It's always there doing work for me.
Mark: [21:08] I ended up deciding to rename it right after I'd already published Redux Starter Kit 1.. That was awkward. Fortunately, the community has taken to it pretty well. I'm still seeing a few scattered, a couple thousand downloads a day for Redux Starter Kit, which is still scary.
[21:28] The growth curve for Redux Toolkit, if you look at npm stats, it's a dead, straight-angled line going upwards. It's up to 25,000 downloads a day at this point, which is not nothing.
Joel: [21:44] It's good, and people are using it.
Mark: [21:47] The feedback is almost universally positive. On an almost daily basis, I'm getting people pinging me on Twitter and Reddit and stuff, and saying, "I've used Redux before and I didn't like it. I've tried Redux Toolkit and it's amazing. It makes everything so much easier."
[22:07] About the only negative feedback I've gotten over time is people who don't like the very opinionated choices I've put in, like having Immer as a non-negotiable default in some of the reducer logic. I can live with that. Clearly, it's helping a lot of people. That is the goal.
Joel: [22:28] If you don't like it, it's [inaudible] or do something else but it's you taking a stand. To me it's interesting just because what you've described to me, your process and how you've gone about this over the years, is essentially very good product development.
[22:44] You listened to your users. You've talked to your clients. You've looked at their pain, addressed that in a sensible way through a consensus even and presented that solves the 90 percent use case. There's always going to be 10 percent of people that don't like your product. It's just not for them, and there's so many choices.
Mark: [23:07] I would definitely take credit for driving the vision of Redux Toolkit. In fact, as I was getting close to 1., I had a specific issue where I laid out, "Here are the goals that I'm trying to hit. It should reduce boilerplate. It should simplify the 80 percent use case for common tasks. At the same time, it should try to stay visibly Redux."
[23:37] I've seen a lot of abstraction libraries that basically hide the fact that you're using Redux under the hood. Those are perfectly fine tools. If you want to use those, that's totally cool. My goal is to not hide the fact that you're using Redux. It's just take away all the annoying aspects of using Redux.
Joel: [23:58] I want to back it up just a little bit to the ideas around state management. What, to you, would be the big ideas that people should be thinking about when they start considering how are we going to manage state in our application?
Mark: [24:15] Good question. I'd say it's a combination of, at a high level, what kind an app am I even building in the first place? Is it a base, simple CRUD app? Is it mostly read only? How long does the data need to live? Does the data need to hang around as I switch between different parts of the UI? Does the data need to change over time as I am interacting with it or is it fetch it, read it, throw it away? Stuff along that line.
[24:56] Those questions really start to dictate what tools are most appropriate for your own use case. I'll even give a specific example. I was just put on a new project at work. New project to me anyway. It is, sadly, an AngularJS 1.x app. I kid you not.
Joel: [25:20] That's going to require some remediation, I would think. You're going to have to...
Mark: [25:23] Yeah. I had never worked with any Angular in my life and I did not want to, but here I am.
Joel: [25:31] Work is work.
Mark: [25:34] It's a got a rest-ish API. The frontend is basically charts and dashboards. You go to a category page, you add a bunch of filtering options, you see your list, you see your dashboards and stuff. The data doesn't last beyond that one category page that you're own, but the queries can get pretty arbitrarily complex as you add different sorts of filtering options.
[26:03] Long term, of course, I am looking to migrate the entire thing to React and Redux. I already went in and converted the build process form whatever Gulp-based weirdness, to using Create React Apps build tooling to build this Angular 1.x app, which I then went and wrote a blog post about because it was very cool.
[26:26] Point is that long term, in the new code base that I'm hoping to eventually set up, I don't see myself using Redux on this code base. There's just not enough reason to use Redux in this app.
[26:44] If anything, I'm seriously considering trying out GraphQL for the first time. I've never worked with it before, but the idea of needing to be able to query lots of different data, where there may be relations between it and you need to fetch several, different, related types of data, probably in one call, seems like a really good fit for GraphQL.
[27:06] On the other hand, the other couple of apps I've worked on have had lots of interactivity, lots of sharing that data between different parts of the app. It changes over time. That's a much better fit for Redux. It's all about understanding what your use cases are, knowing what tools are out there and being able to intelligently decide what tools are a good fit for what problems you're trying to solve.
Joel: [27:34] That's really good advice, just in general. It goes beyond Redux and React because five years from now we're going to be building, the web's still going to be here. That I'm pretty sure of.
[28:01] Do you see it holding on? Is the community there? Is there enough apps and interests? Does it just evolve with the times? Do you keep thinking about what people's problems are? Is it a bad idea? I don't think at the core it's a fundamentally bad idea when you get that. You might get questionable implementations at the end of the day.
Mark: [28:20] Are we talking about the future of Redux and where it fits in...?
Joel: [28:22] Yeah, where is Redux? Is it here to stay?
Mark: [28:26] Yes and no and yes. My rough estimates based on download counts and Twitters polls and such, over the last couple years, have been that Redux has been used in somewhere around 50-plus percent of React apps. I will say that if you look at the download charts for React and Redux, you'll see a pretty close correlation between them.
[28:58] That's being influenced, honestly, by the WordPress block editor called Guttenberg. WordPress is a gigantic portion of the web. When that came out, I saw a noticeable spike in downloads for both React and Redux.
Joel: [29:16] Gatsby as well, which I think people might be surprised to learn that Gatsby is one of the most complicated and interesting Redux apps I've ever [inaudible] .
Mark: [29:25] Gatsby uses Redux in any way?
Joel: [29:27] Yeah, go peek at the internals in Gatsby. It's Redux and Relay. It's an interesting project. It's straight up in your wheelhouse and might be good for your general marketing.
Mark: [29:41] I will have to take a look at that. I was not aware of that one. Something with 50 percent market share isn't just going to disappear.
Joel: [29:50] Gutenberg was a huge project. I remember because they almost switched to Vue or something, because they had some controversy.
Mark: [29:58] They were concerned about the React patents license.
Joel: [30:02] Facebook's licensing, but that was corrected.
Mark: [30:05] At the same time, like I said, there's lots of other good tools in the ecosystem and they do heavily overlap with the kinds of use cases where people might have had just gone with Redux in the past.
[30:18] A lot of people had chosen to use Redux because they just wanted to avoid prop drilling. If that is your prime concern, guess what, Context does that just fine these days.
Joel: [30:29] We've been really into the idea of, and this is from Michael Jackson and Ryan Florence, the idea of composition. We can compose groups of components and avoid these things. We don't always have to reach written context even. Context is often, you really should think before you reach for that.
[30:46] You should think before you reach for Redux or whatever sort of dependency, because you have to live with those decisions too. This app is going to live for years, and it creeps. It's like you said. Years from now, you're going to look back at that, and it'll be the new Angular 1 five years from now.
Mark: [31:02] COBOL. In all honesty, Redux is well past the peak of its popularity. I expect the relative market share, however that gets measured, to shrink overtime, which is an awkward thing for the primary maintainer to be saying, but I am generally a realist.
Joel: [31:25] You strike me as such.
Mark: [31:27] At the same time, people are using Redux because they have existing codebases. People are using Redux because they like it, and it solves their problems. Unfortunately, people are using Redux because it's being thrown at them in week six of a bootcamp, and they don't have any other choice. All those factors put together, Redux is not going away for a long time.
[31:54] It'll probably settle down around 25, 30 percent market share, just pulling numbers out of nowhere. That's still a sizable player in the React ecosystem. There are certainly questions to be answered about how it will fit with where the React team is going long term, Concurrent Mode...
Joel: [32:14] Suspense and all that, Concurrent Mode.
Mark: [32:18] With Concurrent Mode, what's probably going to happen is we'll wind up putting out a React Redux version 8 that uses a new hook that the React team has merged in but not published yet called useMutableSource.
Joel: [32:33] It sounds interesting.
Mark: [32:37] It's something that they basically designed literally for Redux, but also for other similar tools. It's a compatibility layer to allow external state management tools to not completely break React's modified rendering cycle, if I could summarize it vaguely in a sentence.
Joel: [33:00] Right at the boundaries is how I understood it. Like you're on this escape hatch, at the edge of the thing.
Mark: [33:11] I haven't dug into it any further beyond the issue in the PR where it was being put together, but that's probably what's going to wind up happening somewhere after Concurrent Mode comes out for real is, we'll work on a React Redux version 8 for compatibility purposes.
[33:26] I still don't know where all the Suspense stuff is going to end up largely because Suspense is still not in a really usable form.
Joel: [33:33] I literally don't know if anybody knows that. There might be two people on the planet that know that. Maybe a couple more, I don't know.
Mark: [33:39] Andrew and Seb, maybe Ryan Florence, I don't know. I'm content to let that one sit in the background and focus on other things like trying to rewrite the entire Redux documentation by myself, things like that.
Joel: [33:56] That's a challenge. It's interesting to me because I talked to JD Dalton about Lodash and its mission. It's this utility library. Ultimately, what he would prefer is that he wants to always be the fastest. He's always competing against browser implementations, but he will concede if the browser implementation is the faster one. Then, Lodash will just defer to that and use it under the hood.
[34:19] It's like as React evolves, you're evolving the tool to match the platform that it exists within until such a time. Maybe it's just obviated totally or the last user fades into the background. I don't know, these things live for so long. It amazes me how long some projects and code will persist over time.
Mark: [34:46] Code is simultaneously completely disposable and yet infinitely long-lived.
Joel: [34:51] Yes. Code that just works, I don't want to touch it. Just let it run, it should be OK. Sometimes you have to kick it. I didn't prep you for this at all, but are you in a situation where you could show us how the Toolkit works?
Mark: [35:10] Screen shares and stuff?
Joel: [35:11] Yeah.
Mark: [35:13] Good question. I've also never tried to do a screen share with Zoom before and also this is occupying my monitor at the moment. If you can give me a second or two.
Joel: [35:23] It takes is over.
Mark: [35:25] All right, I see a screen.
Joel: [35:29] I want to start a new application. We're just going to build a counter. We'll go with the tried-and-true and make the...I want a counter app. I desperately need to count some things. My chickens, they're about to hatch.
Mark: [35:44] I could shortcut that process for you a little bit.
Joel: [35:47] If there's a template that just says, "Install counter," that's maybe too simple.
Mark: [35:51] We literally have that.
Joel: [35:53] Let's do it.
Mark: [35:54] If you were to try create-react-app --template redux.
Joel: [35:58] OK, npx...
Mark: [35:59] Yeah, npx create-react-app redux-counter-app.
Joel: [36:06] Is it a hyphen thing?
Mark: [36:07] Whatever we want to name the project, so redux-counter-app --template redux. We'll see how fast your network connection and your file system are.
Joel: [36:25] I got all the hot goodness over here.
Mark: [36:28] You're clearly not running this on a Windows system because it would have taken way longer to extract all those files. Honestly, you know what? Just walking through the counter app would be a fairly good example.
Joel: [36:44] Let's check it out. I'm a big fan of counters and todos. People are always like, "Oh, sorry, it's a counter," or complain about it, but it's like, when you're doing an example, the last thing that you need when you're trying to learn something or teach something is to explain the domain of the example.
Mark: [37:02] I have major thoughts about this because I'm literally trying to write a brand-new, quick-start tutorial page for the Redux docs. I spent so much time trying to come up with a plan for what the new example app in that should be, because you're exactly right.
[37:20] It needs to be big enough that it can show off the concepts, but not complex enough that everyone gets confused as to what it is you're really trying to teach in there. Counters and todos are much maligned at this point because they're overused, but at the same time, they illustrate the basic data flow.
[37:43] Like a todo app, it shows form inputs and modifying data, and filtering, and drawing lists of stuff.
Joel: [37:52] You can get all async with it.
Mark: [37:53] Yes.
Joel: [37:54] You can make it multiplayer. You can do so many things. You don't have to explain it to anybody, because literally everybody understands checking todos. It's such a simple domain space, too. You don't have to bother with any of that stuff.
Mark: [38:09] The example app that I've been attempting to build for myself over the last few days has been somewhere in between a Facebook and blog and a Twitter-ish kind of thing. You've got some posts and some notifications, and some users and stuff. I'm probably trying to put too much in there for an initial tutorial, but I want to get the first draft done and see how it turns out.
[38:35] Where do we want to start? Let's start with the store file, app/store.js. The first problem that Redux Toolkit tries to solve is it takes too many steps to set up my store. What is this applyMiddleware and this compose in that really weird double-underscore Redux DevTools extension window thing that I'm having to copy and paste from three different repos sets of instructions?
[39:11] What configureStore does is it calls the standard Redux createStore function underneath the hood, it accepts some named options arguments instead of positional parameters, and it automatically sets up the store with some good defaults.
[39:31] It automatically configures the Redux DevTools browser extension connection, right away. It automatically adds some middleware that will catch things like accidental mutations, both in and out of your reducers, and it adds the Redux Thunk middleware by default, because basically every app already has that right away.
[39:56] As you're seeing in here, you can either set up your own route-reducer function and pass that as the reducer argument, or you can import your slice reducers and pass them as an object, and it will call combineReducers for you automatically.
Joel: [40:15] Is a slice reducer effectively taking the concept of the global data store and literally slicing it into something that's named and contained?
Mark: [40:25] Yep.
Joel: [40:25] Probably, I would think, reduces the re-render issues where people will probably be...I've heard that complaint that with Redux you have to re-render everything.
Mark: [40:34] This is another thing that goes back to the genesis of Redux. With Flux, we had individual stores, so in a blogging application you would have a users store, a posts store and a comments store. When that got translated to Redux the idea was that you have a single reducer function that manages your whole state.
[40:56] That state is probably an object, and you're probably going to have your data in that object divided up into state.users, state.posts and state.comments. The recommended default pattern is that you have a smaller reducer function that manages each of those slices of state.
[41:18] I can remember a specific conversation I was having in Reactor Flux in 2016 where at the time the only term we had was sub-reducer, and we were brainstorming trying to come up with something and eventually someone came up with slice reducer. I used that in some of the documentation that I wrote about how to organize reducer logic.
[41:40] From there, we've ended up adopting the term slice now to refer to all the logic related to managing and updating one specific portion of your state-tree. If you look up there on line 2, we have, import counterReducer from '../features/counter/counterSlice'. Why don't you jump over there?
[42:07] We mentioned earlier that there's a lot of patterns around Redux that are conventions that you don't have to literally do. Redux itself doesn't care what your file structure is. It doesn't care if you've written your action strings as constant variables or inline strings, whether they're uppercase, lowercase, past tense, present tense, whatever.
[42:35] It doesn't care whether you've put all the logic in one file or split it across multiple files, but the docs have shown certain patterns and people adopted those patterns. One of the patterns was that you have your actions folder, your constants folder, your reducers folder. If I had logic for my counter, I'd have actions/counter.js, reducers/counter.js, constants/counter.js.
[43:03] There's a very good reason why one of the most common complaints is, "I have to touch too many files to write any Redux logic."
Joel: [43:11] You're bouncing around having to think about it all. Where is that, where does that get stored, which one is that? That sort of thing.
Mark: [43:18] Eric Rasmussen, who created the Redux Form library, relatively early on, came up with a suggested pattern that he called ducks.
Joel: [43:25] I remember that.
Mark: [43:26] He suggested, "Why write these as separate files? Put your action types, action creators and reducers in one file, default export the reducer, name export the action creators, and it's all in one place." To be honest, for a long time I had some philosophical issues with that pattern, because it obscures some of the intended usages of Redux.
[43:49] We want you, if it makes sense for you app, to have many different reducers responding to one action and if you put all the logic for a feature in one file, it suggests subliminally that only this reducer can handle those actions. It is also possible that if you start trying to import things between different ducks files that you could end up with some kind of a weird circular reference issue going on.
[44:19] Having said that, this is definitely one of the number-one complaints that have come out of the community, and so I've turned around and said, "You know what? Fine, we are going to recommend the ducks pattern as a recommended way to do things specifically, so that people are ending up in that situation with a dozen different files for one feature as a default approach."
[44:42] If you look in here, there's a function called createSlice(). It builds off of two other functions that come with Redux Toolkit that it uses internally under the hood. One of them is createAction(), which takes a type string and generates an action creator that uses that.
[45:06] The other is createReducer(), which is the five-millionth implementation of a function that takes a look-up table of string types to reducer functions and handles them all for you. We've had that recipe in our docs since literally version 1. and yet there's been dozens, hundreds of libraries that wrote their own, but our version uses Immer inside.
[45:37] CreateSlice builds on those two APIs, which you can still call separately if you want to.
Joel: [45:44] Is Immer why we're able to do this where it's state the value and not a...?
Mark: [45:46] Exactly. What you're seeing here is several different factors. Starting off on line 4 you pass in a name field. In this case, the name is counter. This is going to get used as a prefix for generated action types. Rather than having an action type of say, ADD_TODO, we're going to start the action name with a lowercase counter.
[46:23] Then, what is really important about Redux? It's the reducers and how they update the data. You provide your reducer functions as an object here and you give them reasonable-looking names in there like increment, decrement, and add incrementByAmount.
[46:47] CreateSlice will concatenate the name of the slice, counter, with the name of the reducer, increment -- put a slash in between -- but you don't even have to worry about the action type string anymore. It's basically an implementation detail.
[47:05] If you scroll down about five lines, it automatically generated action creators with the same names as the reducers that you provided, and it included them under this actions object from the returned value. You can access the action type field on there if you really, really, really need it, but most of the time you don't even have to worry about it.
Joel: [47:30] It's just calling actions directly. We're literally making method calls on an action's object at this point.
Mark: [47:37] The actions object just has actions.increment, actions.decrement, etc. Now you would call increment() and use that with this batch like you would if you'd written it by hand.
[47:50] The other thing is writing nested spread operations is a royal absolute pain and accidental mutation is the number one mistake that people make.
Joel: [48:03] Frankly, I love them, but I understand what you're saying. They're just fun. I like the arcane symbols, the way you get with programming computers, it makes me feel like a wizard. Anyway, I agree with you.
Mark: [48:18] I've written a ton of nested spread operators. I don't want to write a nested spread operator again in my life if I don't have to.
Joel: [48:25] They're not quite like nested ternary operator to me, but it's getting there.
Mark: [48:32] Yes, this uses createReducer, which uses Immer internally and so you can mutate those objects and arrays to your heart's content, and it does correct immutable updates as if I'd written return...state value, whatever.
Joel: [48:50] Michel's the real wizard.
Mark: [48:53] Absolutely. That right there just saved us a whole bunch of code, because we're pushing people towards a pattern that has all your writing in one file. They didn't write an action type. They didn't write an action creator. They didn't write any nested spreads. They just wrote a reducer, gave it a name, updated their data and they got the action creators for free.
[49:20] If you look down there, we have an example of a thunk just to demonstrate the fact that you can write thunks. You can see that we are dispatching incrementByAmount just like you would if you'd written it by hand.
[49:39] That's the two pieces that people will use the most from Redux Toolkit, configureStore to set up the store automatically, and createSlice to write simpler Redux logic and not have to write any of the action stuff by hand anymore. We do have several other goodies in there, including a couple APIs that we recently added. I'll give a quick sales pitch for those.
[50:06] Tell you what, why don't you, if you got a second, go to pull up the Redux Toolkit docs?
Joel: [50:16] This is going to be handy because you're there.
Mark: [50:19] If we look in the API reference...That's a little bit better. Let's look at createAsyncThunk. This is a new API we just added about a month or two ago. There's a very common pattern that we've always told people to use, which is dispatching your start, success and failure actions as you handle async requests so that you can show spinners, process the data, show an error message, that sort of thing.
[50:54] This tends to be, again, very repetitive because, first, you have to create your action types, and your action creators, and you have to write your reducers, and you have to dispatch your actions. In most cases, it's just dispatch start, fetch something, on success, dispatch catch, dispatch failure.
[51:16] What matters here is the unique async logic you have in trying to fetch something and preparing the payload that you want your reducers to handle. The process of creating those actions and dispatching those actions tends to be very similar.
[51:38] CreateAsyncThunk is specifically designed to abstract away that common pattern. You provide a base action type string, and like with createSlice, it will auto-generate actions for the pending, fulfilled, and rejected cases.
[51:59] Then, you provide a function that does some kind of async work and returns a promise, and then we dispatch the fulfilled or rejected actions based on how that promise turned out.
[52:13] We don't care what kind of an API call you're making. We don't care what kind of an AJAX library you're using. It doesn't have to be an AJAX call, as long as it returns a promise or throws a rejected promise, do whatever you want in there.
[52:29] Then, we also leave it up to you to decide how your reducers are going to handle it. You can use Booleans, or enums, or whatever you want for your loading state. You can process the data however you want. This at least simplifies the standard processes for working with some async types of fetching. We...
Joel: [52:50] Previously, you'd end up with 50 lines of code across several files. Would be the pattern people have in their head, I guess.
Mark: [53:00] Because this is supposed to be fairly generic and reusable, we did add some extra complex-use case scenarios in there. It automatically tries to see if AbortController is available, and if so, exposes an abort method on the returned promise so that you can at least try to signal to your code that maybe it should bail out of the request that it was making.
Mark: [53:39] Canceling thunks has always been a point of complaint, so we at least tried to provide some mechanisms where you can cancel things if you have a need to do so.
[53:51] The other big thing we added in version 1.3 is createEntityAdapter, which is over there on the left side. The docs have recommended for years that you should try to store some of your data in a normalized form, which means that if I have a whole bunch of posts or users, rather than storing them in a single array, I should have them in a lookup table where the keys are the IDs, and then the values are the items.
Joel: [54:22] Like some sort of Falcor style. I don't know. That's intense, is what it is, a lot of times.
Mark: [54:30] Kind of making it easier to look up items by ID.
Joel: [54:33] It's quicker. Ultimately, that's something the machine would do. It's not really human friendly, I would think, because you're not...Anyway, go ahead.
Mark: [54:43] I wrote the docs page that tells people you should try to store your data in normalized form. There's been, again, dozens of different libraries that the community has written over time that help manage relational data in some way or form.
[55:01] Even though we've had this official recommendation we've never had any kind of an official tool that we recommend or provide that tries to help with that process.
[55:13] I wanted to try to provide something for that use case. I was looking through a bunch of different packages and comparing the APIs. I came across something from the NgRx team called NgRx Entity. NgRx is a reimplementation of Redux for the Angular ecosystem built around RxJS.
Joel: [55:37] It's just a fun coincidence, I guess, because Rob Wormald is a friend of mine. We were both super into Redux, but we were in Angular land. Then NgRx came around.
Mark: [55:50] I chatted a few times with some of the NgRx folks. "We should have more overlap between our communities or libraries. We're doing almost the same kinds of things here." Looking at their implementation I noted that there were writing like two or three lines of code that made that library Angular-specific. It was this close to being generic and reusable.
[56:16] I found an issue to discuss, like, "Could we maybe tweak it and make it generic?" Then I pulled it down and started playing with it. In the process, I wound up rewriting the guts fairly considerable. I flipped the order of arguments. I converted it to use Immer internally or moved a few pieces that I didn't feel were relevant for us.
[56:37] In the end, I did end up porting it. Again, I'm trying to be very clear, full, full credit to them for having written it in the first place, which is fair because NgRx was inspired by Redux in the first place. Collaboration...
Joel: [56:52] That's part of the joy of the thing anyway. Assuming credit is given where credit is due, that's the spirit of the whole community.
Mark: [57:01] Ultimately what this does is it provides a set of functions that are effectively generic reusable reducers for inserting, updating, and removing normalized state. Like I just received an array of posts from my backend, and now I want to convert it from an array into a normalized object and I want to shove it in there.
[57:30] Rather than have to write that logic by hand every time, this provides APIs like upsertAll or addOne that can do that generic logic for you. We don't dictate what actions those are hooked up to. You can use them as reducers by themselves or as part of a larger function.
[57:59] The point is that it is something official. It doesn't solve all use cases, like this doesn't do anything about the relations between the data, but it's at least a minimal, viable tool for implementing something that we've been recommending for years.
Joel: [58:18] It's a pretty complicated problem, I would say, in general, the way the data plays. I've got to say this doesn't look like Redux at all to me, in general. The whole tour. That's not even in a bad way. I'm just saying when people are talking about Redux, they're not talking fundamentally...They are, but they aren't talking about the same library.
[58:39] A lot of the core stuff is still there under the hood, but there's abstractions laid on top of that. I assume that there's escape patches where if you want to go old school on some Redux, you can do that all day long.
Mark: [58:57] Oh, yeah.
Joel: [58:57] Everybody is expecting a switch statement in your reducer, a giant switch statement that's a reducer. In fact, I saw an example of a useReducer today that was just a ternary. Frankly, that's fine. That is still a logic gate and you return the value that you need. You don't need all this other stuff.
Mark: [59:16] Here's the fun flipside of that. I've written a few different components in the last year or so where I needed some fairly complex useReducer logic. It's component state, but it's complex enough. I need a reducer. It's kind of complex reducer, but I wanted to have good TypeScript typings, too.
[59:38] Redux Toolkit itself is written in TypeScript. I have a co-maintainer, his name's Lens Weber. He has done some amazing work to make our types work correctly. I used our createSlice API to generate a reducer function that never got used in the Redux store at all. It only got passed to useReducer. It works great because a reducer function doesn't have any dependency on Redux itself.
Joel: [1:00:17] To me, that was one of the reasons the whole thing has been beautiful the whole time. Like the concept of reducers and using them, it frankly changed my way of thinking about how I program on some levels. It's a simple concept, but like you said, it's extremely powerful and versatile. You can throw whatever reducer function in there and get results.
Mark: [1:00:41] One of the projects I worked on had a bunch of Python services on the backend. They were doing a lot of mutable threaded updates to cache state in memory. The thought has occurred to me a number of times that if I processed this data using some sort of a Redux-like data flow, I could probably get rid of all these lurking statements around that.
Joel: [1:01:10] I think it's event sourcing is...That's where a bunch of, from what I understand of event sourcing, was the backend...
Mark: [1:01:17] Even just doing immutable updates at all rather than trying to update data structures in place.
Joel: [1:01:21] That string of words, that caching in it too made my line at the end of the day. I'm like, "Oh, man. That's..."
Mark: [1:01:31] Twitch, twitch.
Joel: [1:01:33] Yeah. Mark, I want to say I really appreciate this tour. Honestly, it's interesting to me to see this. My overall goal here is I'm going around and I'm talking to different maintainers. David K Piano is going to show me a little XState. I want to get a clear picture of where React state management is at this point.
[1:01:57] At Egghead, I'm asking our users, "What are you confused by?" This hasn't changed in the last five years. It's state management. That goes way beyond React and Redux. It's a hard problem space for people to get their heads around. I love that you are out there listening to people and maintaining this and improving it. It's really great.
Mark: [1:02:19] If I can take a second to show you what I'm working on right now.
Joel: [1:02:22] Yeah, let's see it.
Mark: [1:02:23] Go to the main Redux repo, github.com/reduxjs/redux. That looks familiar right there. 3740.
Joel: [1:02:40] Was that the one?
Mark: [1:02:41] Yes, it was.
Joel: [1:02:43] Nice. This is why we're talking. I was looking at this stuff.
Mark: [1:02:46] Probably yeah. Let's scroll up to the top and pop open the preview link at the bottom of the comment there. Keep going.
Joel: [1:03:00] OK.
Mark: [1:03:01] Pop that open in a new tab or something. This is what I've been agonizing over for the last several months. The Redux documentation as a whole desperately needs to be rewritten. I first put up an issue proposing that two years ago.
[1:03:24] A lot of other stuff has happened. React Redux Version 7, 7.1, Redux Toolkit, everything else. In all honestly, this has turned into a one-man crusade because I'm not getting a whole lot of assistance on any of this.
Joel: [1:03:39] Nobody wants to write docs, people that would like to break into open source and are always looking for ways to contribute.
Mark: [1:03:49] I have a huge overview issue where I'm listing all the stuff that has to happen.
Joel: [1:03:56] That's the comment that I'm locked on, is your...I was scrolling through this and looking at your structured issue where you're talking about what needs to be done and how the demo should be.
Mark: [1:04:09] There's another whole issue docs rewrite overview where I link to a dozen other sub-issues for things I want to do, like changing to the docs as a whole. Adding this, rewriting the main tutorial, adding a real-world usage section, adding a thinking in Redux section, shuffling things around, all kinds of other stuff.
[1:04:33] This is just one individual task within that master list, but it's something that I feel is incredibly important for a couple of reasons. The Redux docs as a whole are outdated because they were originally written in 2015 in an entirely different time.
[1:04:52] Remember when I was talking about that Flux thing earlier? Nobody remembers what Flux was, and especially not people coming into the Redux docs in week six in a bootcamp. The tutorial even says if you've ever written a Flux app before, you'll feel right at home. That means nothing to anybody.
[1:05:13] The current tutorial is telling you, "Write your uppercase caps constants and your /reducers folder and all this other stuff." In the near future, my next task after this would be to try to rewrite the main tutorial, the bottom up tutorial that is still teaching you how everything works from the beginning, but simplify it, teach you easier to use patterns, clarify the explanations, etc.
[1:05:42] Then finish it by saying, "Now that you know how to do stuff by hand, don't do it by hand. Here's Redux Toolkit. That's the right way to do it." What I'm working on here though is a brand-new quick start tutorial.
[1:05:56] The goal for this page is we're going to assume you've never used Redux before, you just want to know what is this thing, why should I use it, and how can I start writing code with it as fast as possible. I don't need to know how it works. Just show me examples that I can mimic and start getting something working.
[1:06:22] Ryan Florence has commented several times on Twitter that he got involved in Rails and he knew nothing about proper API design or whatever, but he was able to follow the examples and start pumping out something that was useful.
[1:06:38] That's the mindset that I'm going for here. Just enough of an intro to Redux that you understand the concepts, what they are, and what some of these pieces, how they fit together. Then enough of an example app that you can see the patterns to follow. Then you can start using it. When you want to know how it works, you go over to the main tutorial sequence and work through it.
Joel: [1:07:03] That's like a deep dive versus...
Mark: [1:07:07] It's top-down versus bottom-up. If we look at that preview that I've got so far, I'm not entirely convinced that this is the right direction to go with it, but my goal is to get the first draft complete including the example app, and then hopefully get a whole bunch of feedback and critique it.
[1:07:28] What I've ended up with is is page one explains what Redux is, what are the terms and concepts like actions, reducers, and dispatching. Then it walks through that counter template example that we were just looking at in...
Joel: [1:07:43] The same tour that I just got.
Mark: [1:07:44] Literally the same one. The other thing we didn't see over there is the Hooks API. The counter now comes with our React Redux Hooks API as the default. That's what we're going to be teaching people as the default.
[1:08:00] Part two is going to be building out an example app, something kind of mock social feed, Facebook, Twitter-ish, adding some posts and fetching some data and updating reactions on a post and stuff. Hopefully, that's enough of an example that people can see the concepts without panicking over how complex the app is.
[1:08:30] I've got maybe two-thirds of the first cut of the example app written. I'm just trying to get the final form of it done so I can then backtrack and figure out how to show step by step how you get to that endpoint, and then write the other half of the tutorial that tells you how to get to that point.
Joel: [1:08:53] That's what occurred to me when I was looking at that and reading your issue where this is going just because one of the things that we've gotten good at is we have a strong focus on instructional design. I don't know if you spend time with Egghead courses. Traditionally, we would be like...
Mark: [1:09:10] Honestly, I've never gone through any of them.
Joel: [1:09:12] Nice. Not even the Redux one, huh?
Mark: [1:09:14] I watched...
Joel: [1:09:16] You didn't watch Dan literally build Redux from scratch in video form?
Mark: [1:09:20] I watched half of those, but it was well after I already knew Redux. It was more of just about seeing how he was explaining things.
Joel: [1:09:27] Anyway, honestly, that's fine. What we do now is take this instruction design approach and do a subject matter expert interview, and then take that and try to form that into a cohesive instructional unit. I don't know if you have an instructional design background, but that sort of thing has really helped us.
[1:09:52] It's interesting because the end result can be a video course, or it can be some documentation, or it can be an article. The output doesn't matter. It's the input, not the output, that's ultimately what the value is there. To me, what's interesting also is how do you even get collaborators because of your level of understanding and conveying...
Mark: [1:10:19] Banking on Twitter.
Joel: [1:10:19] You have a depth of understanding. It's trying to get people into the same context and to have that level of understanding too. That's why people are intimidated sometimes by docs. I started my whole entire career writing docs for an open source project because nobody ever wants to do it.
Mark: [1:10:36] Same. I got started by writing the FAQ.
Joel: [1:10:40] You get in there. It's a great place to chip in. I'm a big fan of it. It's so much work, especially for one individual. To me, it's hard in a vacuum as well. It's more fun to collaborate at the end of the day. It's just a better thing.
[1:10:59] I don't know if that's interesting to you. I'd throw it out there that we might be able to help in that way. It literally takes an hour, usually, to go through one, and there's no real downside to it. It's less time than we spend on the overview, trying to drill in and get the essence pulled out of it.
Mark: [1:11:21] I took a first cut at just sitting down and trying to write something. I didn't like where that was going. I decided, "You know what? I'm going to step back." I took several weeks to try and read through 25 different tutorials, not just for Redux. Five or six different good Redux tutorials that I liked, but I went through the Vue docs, Angular, NgRx, Ember, Rails, Django, a bunch of other stuff.
[1:11:59] I was just taking notes on what they were trying to teach, but also how is the information formatted, what kind of example apps are they building? Do they have file names on top of the code snippets? What stuff do they do that I like and don't like, and how much of that can I steal for the Redux docs? That "what you'll learn" thing at the top, that is stolen directly from Cypress.io.
Joel: [1:12:34] It's a good one too. It's a great callout. Good design on it.
Mark: [1:12:38] The prerequisites bit, just down a little bit, that is swiped directly from Tania Rascia's tutorials.
Joel: [1:12:48] Her blogs are amazing.
Mark: [1:12:49] Amazingly good. There's an explanation in here on data flow and state management that I literally copy-pasted from the Vuex docs.
Joel: [1:13:02] I like the expandable details. You get the gist, but if you want to deep dive a little more...It's not in your face, but if you need it then there it is.
Mark: [1:13:10] Again, for this page, I'm trying to keep from going into the weeds. I want that information there if they're interested, but I want you to be able to go through it. There is a phrase up there, "Redux is a pattern for updating state based on events" that was in some guy's blog where he was upset that that wasn't in the Redux docs already.
[1:13:34] I'm putting effort into this myself, but I am blatantly taking inspiration from as many sources as possible because if someone else has done something good, I want to use that.
[1:13:45] I would definitely say I have seen a number of people, not just me, saying, "Modern Redux is completely different." In terms of what you saw from createSlice and the Hooks API, which we haven't even looked at in our discussion, there's a whole lot less code to write. There's less indirection, and it's a lot more straightforward to work with.
[1:14:17] There's always going to be some amount of indirection. If you got a second, can you pull up my blog? blog.isquaredsoftware.com.
Joel: [1:14:31] Blog. What? Ice?
Mark: [1:14:34] The letter I, the word squared, S-Q-U-A-R-E-D, software.com. Let's see. Scroll to the bottom.
Joel: [1:14:47] That's not what you expect to see in a...
Mark: [1:14:49] Yeah, I know. You ought to read that post. I had a lot of fun with that.
Joel: [1:14:53] I'll check it out.
Mark: [1:14:54] OK, that one right there, Redux Toolkit 1.. Scroll down a little bit to the post table of contents and click on Dealing with Complexity.
Joel: [1:15:08] Where we at? Dealing with...Oh, OK.
Mark: [1:15:12] Origins, Dealing with Complexity. Going back to, "Why do people not like Redux?" There is a lot of complexity around it. The point I was trying to make here is you can divide it into two categories. Inherent complexity, that is literally part of how Redux is meant to work, and incidental complexity, that is all the other stuff that came along with it that isn't necessary.
[1:16:06] The Connect API has some aspects of that. Connect is a deliberate level of indirection so that your component never has to know that it's even interacting with Redux. It's just getting a bunch of data and callback functions as props.
[1:16:25] You've always been able to do an async call in componentDidMount, and then call this.props.dispatch when it's done. We've always told you that's a bad idea because now your component knows about Redux, and it's not reusable. "Oh, no." Panic.
[1:16:42] The thing is that hooks flip this on their head. If you look through my blog, I had a post in a conference talk around August and September of last year where I talked about how hooks take you in a different direction, and they have a different set of tradeoffs.
[1:17:05] If you click the older posts right there, it's the top couple posts right here. "Thoughts on Hooks and Separation of Concerns" and "Hooks, HOCs and Tradeoffs."
[1:17:21] Hooks push you towards rating components that know how to fetch all their own data. They might not know the exact details of it because it's abstracted inside of a hook, but they're asking for it and not expecting it to be passed in as props. We're removing a level of indirection.
Joel: [1:17:40] locator, I think, would be the old school pattern.
Mark: [1:17:45] That also changes how you think about things like testing. The advantage of HOCs and stuff was you had your presentational component, and all you have to do is pass in some props and verify that it displays what you want.
[1:18:00] Now you need to have a Redux store wrapped around it with a provider in a test, or you need to have your Apollo GraphQL provider setup, or mock out your AJAX call, or something along those lines. On the other hand, it's very obvious where that data is coming from, and it might be less mental overhead for people. It's not that it replaces HOCs. It's a different set of tradeoffs.
[1:18:37] Because of that, that's one of the reasons why I'm going to be teaching our hooks as the default API for React Redux, because not only do I think that's where the React team is going in general, but I think the tradeoffs here are going to be easier for people to get into.
[1:18:56] It's easier to see a function called useSelector that returns a value than to...Even though map state is doing basically the same thing, it's that extra indirection that really seems to confuse people.
Joel: [1:19:13] I agree with that. People understand. It's like smoke and mirrors and human brains. What's clear to maybe a smaller group of people isn't as clear to the larger development community.
[1:19:30] We all have to build apps. People are hiring. You have to have comprehension, new employees churn, and all that fun stuff on any project. It's like a real business issues that come down to [inaudible] , I think.
Mark: [1:19:42] I was having a chat with somebody in Reactor Flux a couple weeks ago who was insisting that if you weren't using Redux "the right way," you should never even be using it at all. He was especially go honing in on the treating your actions as events concept that we do suggest in the docs, and having many reducers respond to one action, and so on.
[1:20:12] I was telling him, "OK. Look, number one, even though I wrote that suggestion, it's something I struggle with frequently. I can't write all my code that way. If I can't do it, how is someone who is just getting into Redux going to know how to do it?
"[1:20:29] If they're just getting into Redux, they're not going to know what the right way is. If they don't stick around using it at all, how are they ever going to get to the point where they know how to do it the right way anyway?"
[1:20:46] In a lot of ways, I wish that we only had very experienced users who knew how to do it the right way because that would simplify my job as a maintainer. I would have to write a lot less tutorials. I would be able to just say, "Yep, here's how you do things. Let's move on."
[1:21:05] What's happening is I've got, again, people coming in from a bootcamp week six, week eight who are being thrown into Redux way too early. I need to take them into account. I don't want them bouncing off of Redux right away. They may, but I want to do everything possible to at least give them a fighting chance to try to understand what's going on.
[1:21:32] Again, I can't do anything about the millions of existing tutorials, and videos, and everything else that are already out there, which show the older patterns. The older patterns still work, but I'm going to do everything I can to make the docs easier to get started with, to try to show patterns that are simpler with less indirection, and to provide APIs that will make it easier to use.
[1:22:00] Redux isn't for everybody. Not everyone should use it or even learn it, but I'm going to do everything I can to ease the learning curve and make life better for people who are using it.
Joel: [1:22:13] I appreciate it. I really do. It's great that you're out there. Honestly, to me, it boils down to trying to help people. That's fantastic. I really appreciate it. I'll let you know when this comes back around.
[1:22:28] Frankly, leading into what you're talking about. "Here's all the decisions. Here's what it's good for. Here's the current reality of it. Here in 2020 is what it actually looks like. Quit watching Dan's videos and go watch Mark's videos. Read the docs." It's time, so I'm going to help out if I can.
Mark: [1:22:47] Cool.
Joel: [1:22:47] Cool. Cheers. It was good talking to you. Good to meet you.
Mark: [1:22:49] Thanks. Appreciate it.
Joel: [1:22:50] Cheers. Bye-bye.