Check out a free preview of the full Redux Fundamentals (feat. React) course
The "mapStateToProps & Connect API" Lesson is part of the full, Redux Fundamentals (feat. React) course featured in this preview video. Here's what you'd learn in this lesson:
Steve demonstrates how to use mapStateToProps and reducers to pull and map objects from the Redux store instead of having a hard coded initial state. A common issue with hot module loading not recognising a change the module tree to trigger reloading is also covered in this segment.
Transcript from the "mapStateToProps & Connect API" Lesson
[00:00:00]
>> The first order of business is right now we have just this JavaScript array, that we're passing into menu items. So it's not actually coming from Redux. The rest of the application is wired up in the same way we saw previously. I'm not gonna go, wrap the application in a provider again.
[00:00:16]
And all that kinda stuff, the dev tools are wired up, the providers wrapping around the application we're just gonna focus on creating the API at this point. So what we'd like to do is remove the need to pass in items as an array that's kinda hard coded in and instead get the array that is kind of set as the initial state within our reducer.
[00:00:40]
Right, which is relatively the same, we'll change this slightly just so we can see it when it's time. Right, so we'll put that in there as well. .So, first thing we can do is go to containers. And we have an example one in here and you kind of see a little bit about how this works.
[00:01:03]
We have Connect, which takes, I think four arguments really, we're all gonna use too, which is mapStateToProps and mapDispatchToProps, right? Each one of these presentational components takes a set of props. What we wanna do is, what do we need to pull from state to pass in as props?
[00:01:21]
What do we need to pull yeah in terms of action craters and map those two different props, and then we'll pass those all into the component that we're wrapping. So let's go ahead and we're gonna create a menu items plural container. Make MenuItemsContainer.js. All right in here, we're gonna start by creating that first function which is gonna it's very similar to what we had with us selector.
[00:01:53]
So we'll say Const mapStateToprops and that is going to take the state as the first argument in there just like the selector did as well. And then what we need to do is return some kind of object where the keys will be the things on the props object, and the values will be what that actually represents.
[00:02:16]
So if we look back over at calculator.js, you can see that this is expecting an items Prop, which should be this array of items. So we just need to make sure that that happens. So we'll go ahead back into menu items container. And we'll return an object that actually has a shape of the props of this component is expecting.
[00:02:39]
And so we'll say okay, cool items is state.items. Awesome. The one thing to note is this is simply a regular old JavaScript function that returns a regular old JavaScript object. You could call this constant or this variable sandwich if you wanted to. The fact that we call it map stage props is just a convention because we are taking things from our Redux store and we're mapping them to the props that the object x Specs.
[00:03:07]
And then finally we will export a menu items container. And that is going to use this Connect method that comes on react Redux. Connect takes the state that you wanna map the props and the dispatch and then eventually it will take a component that you want to wrap and pass those properties too.
[00:03:30]
So we'll say mapStateToProps. We don't have a dispatch yet. This will return a function that eventually takes a react component. This is if you wanted to have some assembly like a with items, connector that you wanna use for multiple components, you could just export this. We're gonna kind of immediately wrap the menuItems Prop.
[00:03:49]
Your menuItems component. Too. All right, let's pull that in. Take a look and we'll say Import Nope. /components. I put all the presentational components in a components folder containers or a container folder again, that's not nothing forcing you to do that. So put that in place. All right, you can see that we've got the menuItems component there as well.
[00:04:30]
And then really all we have to do is go back to this calculator, and we're going to swap out the presentational one for the one that is passing the state into the presentational component. And then we'll switch this out as well. ManuItems from ../containers. All right, let's go ahead and we can actually remove The hard coded in an array because now this component is going to know to pull stuff in from the Redux store.
[00:05:08]
All right [COUGH] as you can see, now we added the it's now gone from Vegan Ham to Vegan Ham Sandwich and an Awesome Tofu Roast instead of a Tofu Roast. So this is now a component that is hooked into the state of our application. The other thing that we might wanna do is figure out how to dispatch actions as well.
[00:05:28]
So it seems like a good thing to get up and running is this new item form up here, this new menu item form. Now, just like we saw in the previous example, this can manage its own state. This doesn't need to be stored into Redux, per se. We really just wanna know, okay, when they hit the Add Item button, that's when we wanna go ahead and add it in.
[00:05:49]
We don't have the concept of an added item or the idea that a user might have added an item yet, so we need to create that action. So here we'll say const ITEM ADDED. All right, so here's the pop quiz time. We look at the form. How many things do we need to know about based on the act of the user hitting that Add Item button?
[00:06:17]
Like what information are we gonna have when they hit that button?
>> Looks like the item name and the price.
>> Name and the price. That's not all the properties of an item, right? If we look back into our reducer. All right, we've got stuff here you ID, the name, the price, the quantity.
[00:06:35]
And so one of the questions comes up is like, okay, where do you like determine the ID? Where do you set the default values? Now, Redux will let you do either. Right if you want to in the action create a set all the default values, that's totally fine as well.
[00:06:51]
Or you can do it all on the reducer my recommendation again since the reducers job is to figure out what a thing that happened means. I choose to move it also reduce and I recommend that you do it all in the reducer. You could set the default values of each in the action, but then you are now chasing around all the default by different parts of the code base versus like taking all of the changing of the world of what a given action means.
[00:07:14]
Putting the reducer where that stuff is happening anyway, for me creates a more maintainable code base. So we'll say addNewItem I really like to use past tense my action names because again, it forces me to think about this in the right way which is this thing happened they hit the button an item has been added.
[00:07:35]
The tricky part around for the action creators is if you want to map it to the like, you'd have to like rename it as you map it. The react components are expecting stuff like on change on submit On add new item, they kind of use a different tents.
[00:07:49]
So, a lot of times it's tricky, but I will tend to just name my action creators as I would see them in my react application. So, as I pointed out, I think we're getting is the name and the price. And this is again, his sole job is to return some kind of object where we've got the type being item added.
[00:08:10]
And then the payload it's just gonna be the things that we know about. This is yes, you could again set all the default values here. I'm going to implore you not to, because I think that all of the implications of a change should all happen in the reducer.
[00:08:23]
So we've got that in place. Now there's a bunch of ways to get dispatch into a component. But first we do also need to add this logic to the reducer cause right now, Reducer doesn't do anything. So we'll go ahead and we'll say if the action.type is ITEM ADDED.
[00:08:46]
I don't know why my auto importing isn't working right now. That's annoying, but we'll deal with that later. We'll say, From ./actions Are important instead. Great, so we've got that in place. So if ITEM ADDED Then what we wanna do is we need to immutably mutate the array which means we cannot push it on to the array.
[00:09:18]
Because push mutates an array, which will not let react know that he has changed when we've discussed before, everything needs to be immutable. So we'll say we'll make our new item. We'll say like uuid is id++ which is incrementing a number. In this case, we will say that the quantity is one as a default, and then we'll spread over the rest of the actual payload that's got the name and the price.
[00:09:46]
And the reason that I have to do this which is, if later we did wanna add another filter for added quantity, whatever get spread last or override whatever was already existing on the object so it will support that in case anything changes. So you can even have a default name and default price in there as well.
[00:10:03]
Anything that comes into the action will override whatever you set as the default. So it's a nice way to kind of have a fallback for everything as well. And then we will spread out everything that is currently in the state which is this wide array of items. With this new item that we created, so we've got this in place and again, this is super easy to unit test because it's simply a function.
[00:10:23]
You can literally just write a just test real quickly and pass in the initial items and action that conforms to what we just said before, and make sure that it's on there. All right, so now we've got an action that we can dispatch Reduce with the knows how to deal with that action.
[00:10:40]
Really we just need to somehow get it into that new item form component, and then we've got that part in place. So let's go ahead. And let's just verify that this works first, which what I'm gonna do is. I am going to go in item added not exported from actions.
[00:11:00]
We just need to export and then we're back. So now I can go ahead and I'll go to Redux and pull up that little keyboard. I don't know why it's a keyboard, dispatch, ITEM ADDED, we see the state two equals so I gotta check something out here, right?
[00:11:22]
And this is where these tools become super helpful. There's nothing different after we dispatch the item ITEM ADDED event, which is we've got the name, the price. Let's go ahead and check out our reducer. I don't type just to make sure I saved it. I should have been cause we didn't load before.
[00:11:44]
All right, so of action types item added, we can go ahead and take a look. Let's try it one more time, just real quick. I'm gonna refresh this because I have a hypothesis. All right, it works. This actually points out a really great thing that trips me up all the time, which is so this is based on create react app, which has hot module, reloading.
[00:12:03]
Hot module reloading checks your module tree to see which, which components changes and swaps them in. You'll notice a lot of times that even as we change stuff, we still have the same state in place. Just changing plain old JavaScript stuff doesn't always retrigger hot module reloading. So, if you find that like you haven't touched a component.
[00:12:22]
You've only touched like regular JavaScript in this case redox and you don't see your change on there. Sometimes you have to refresh the page that bites me more often than I'm comfortable admitting.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops