Transcript from the "Reducers" Lesson
>> Brian Holt: Let's actually get started, like what actually makes Redux, Redux. You're gonna have a data store, the data store is where the central place for all of your state lives. But you cannot directly modify the store, except in what's called a reducer. Now that's a intimidating word, at least it was for me.
[00:00:19] Cuz when you say reducer, that's meaningless jargon to me, personally. Cuz I don't come from a functional background, which is where it comes from. But a reducer is probably something you might have used before. So if you do array.reduce, the function that you pass to that reduce call is called a reducer.
[00:00:43] If you ever used the reduce function call, you've created a reducer before. So those are analogous concepts just keep that in mind. What a reducer does, all a reducer should do is it takes in state and an action and returns a new state. That's it, there's not much more magic to it than that.
[00:01:08] Many reducers are as simple as like three lines of code. In fact, most of them that we're gonna write today are literally three lines of code. But it's key that we get here to the functional programming paradigms here, that with a reducer, you're gonna take in a state, you're gonna take in an action.
[00:01:23] You're not gonna modify either one of these and you're not gonna have any side effects from within your reducer. Meaning, you're not gonna modify any external state. All you gonna do is you're gonna take in this old state and then an action. You're gonna apply some transformation, you're gonna modify the state in some different way, but you're not gonna modify necessarily the old state.
[00:01:43] You're going to create a copy of that state, the new state, and you're going to return that. So you have no side effects, side effects being that you don't modify any state that lives on perpetually.
>> Speaker 2: Question, does Redux do any compression or memory optimization?
>> Brian Holt: No.
>> Brian Holt: No, you can.
[00:02:08] But Redux itself is just a central repository for what ends up being a rather large object. That's really what Redux is, is a fancy wrapper around an object. That is reductive as all get out. But that's maybe a good mental model to start with, that it's just a big object.
[00:02:32] The store is a big object and then reducer just takes a big object, does some transformation and creates a new copy of that object with the new transformation and then returns that. And that's now the new object, the new store. This is not very concrete yet but as we start writing hopefully you'll understand a little bit more.
[00:02:55] So your store is going to have what's called a root reducer. It's going to always call the root reducer first. Now technically, you could just do all of your logic inside of the root reducer. That's not a good idea. Typically, you wanna just dispatch that to another reducer.
[00:03:14] So if you're coming from a flux background, that's kinda like the dispatch. The dispatch is kinda like the root reducer, it's not necessarily quite analogous, but it kind of serves similar purposes. You get your root reducer called, your root reducer dispatches to another reducer that does the transformation, and then you end up with a new state.
[00:03:40] So let's actually go create our route reducer real quick. So create a new file, save it, and call it reducers.js. Notice I do lowercase r, cuz this is not a component. That's why I do that. It's not a constructor or anything like that. It's just a file with some logic in it.
>> Brian Holt: Okay, reducers.js. First thing we're gonna do is we're gonna create the DEFAULT_STATE. This is going to be the state that it starts up with. This is like the getInitialState of Redux. So search term is going to be an empty string. This is what we're gonna migrate to the Redux, is our search term and everywhere that keeps track of that.
[00:04:36] We are gonna have, const rootReducer, this is gonna be just a function. So your gonna say (state, action).
>> Brian Holt: So usually your root reducer ends up being a big switch statement. Now, I know someone's gonna ask this so I'm just gonna preempt the question that's gonna come up.
[00:05:09] There is a function called combine reducers that makes this root reducer stuff a bit easier. We're not gonna do it today, cuz I think it's better that you explicitly understand what combined reducers is replacing. So we're going to write our own root reducer instead of using combine reducers, but feel free to check that out on your own time.
[00:05:27] I don't actually remember it well enough to write it on the fly, but it's not super complicated. Okay, switch (action.type).
>> Brian Holt: So, I don't use too many switch statement, but this is a really good time to. Every action is going to come in with some sort of data associated with it.
[00:05:52] And it's always going to come in with a type. Every action must have a type. And the type is going to determine where you route it. So you're going to route it to this reducer, or this reducer, or this reducer. So it kind of determines how it gets run.
[00:06:10] The first one that you're always gonna write, there always must be a default thing to do. So, you're gonna write, default:.
>> Brian Holt: Which basically means hey, you passed in an action type and I don't actually know what that does. I don't have a reducer for that, you need to provide for that particular case.
[00:06:29] If you don't know what to do with it, all you're going to do is return state. So state is going to be the state of your redux store at any given time.
>> Brian Holt: In this particular case nothing changed, so we're just gonna say okay, the state of my state is going to be the state that it was.
[00:06:48] Nothing changed so just keep being whatever you were. The other thing that we need to do is we need to have some default state when we start up. So what you could do is state = state or DEFAULT_STATE. This is kind of the old way of doing it, old way, quote unquote.
[00:07:36] However, we're writing ES6, so we can get even more clever than that. We can just say =DEFAULT_STATE, which basically says if this is undefined, then it's this. And then we can just get rid of all that. That's called a default parameter.
>> Brian Holt: Except I think I have to put a space there.
[00:08:03] Or else the is gonna yell at me.
>> Brian Holt: And then down at the bottom, export default rootReducer. So, yeah?
>> Speaker 3: Would it be a good practice to define a default action as an empty object?
>> Brian Holt: You should always get an action.
>> Speaker 3: I mean the parameter action, like if you're using default arguments.
[00:08:37] Like, if you passed in something that wasn't an object and then it tried to do switch.type with that error.
>> Brian Holt: Yeah, I guess if that was a problem. But again you should never get a null or undefined action. That should just not happen. Now, I'm never against making your program more resilient to bad data.
[00:09:01] Because this is messy, shit happens, but it should never happen. It's reliable enough that you can sidestep it if you don't want to do that.
>> Speaker 2: Question from Richard, do you use data normalization, and when do you think data normalization is required?
>> Brian Holt: Definitely way beyond the spec of this course.
[00:09:23] I mean obviously data normalization is helpful in some regards. But, one, I don't know if I know enough about, or if I have enough opinion about it to have an intelligent conversation about it. But, there's plenty written on normalization with Redux if you're interested about it. I would take a look at that.
>> Brian Holt: Any other questions? Sorry for the crappy answer but it would take way longer to talk about than we have time for.
>> Brian Holt: So, this is like the barebones, hello word reducer, right. This is at least the bare minimum that you need to get up and running.