5.4 Create the Edit Card Modal
In this lesson, we'll create a modal for editing or deleting cards. This will be pretty simple, because we can reuse the
CardModal presentational component.
1.Introduction2 lessons, 04:39
2.Get Started With Redux6 lessons, 41:43
3.Create React Components8 lessons, 50:18
4.Application Structure9 lessons, 56:09
5.Implement the App9 lessons, 1:31:34
6.Conclusion1 lesson, 01:32
5.4 Create the Edit Card Modal
Now that we can create interview cards the next step is to actually be able to edit those cards. In this lesson we're going to give our application the ability to edit and also delete cards. This is actually going to be a great example of adding a feature to every single piece of our application. Currently no part of our application really has any idea about editing cards. The only thing we have is that when we're displaying cards we have an edit button. But other than that there is nothing in our application that knows about editing and so we get to start from scratch. We have to build action creators, we have to build a reducer, we have to build components, all of our moving parts are going to get some additional code In this lesson. So let's start with our action creators. Let's go ahead and export a constant. We'll call this one updateCard and it's probably gonna take the card as a parameter. And this card is not going to be necessarily the whole card, but it's gonna be an object with the properties that we wanna change. So, let's go ahead and return an object will have a type of update card and the data of course will just be that card. While we're here, let's also export a constant for delete card, and for this we will expect the card ID as our parameter, and let's give it the type of delete card and the data will be cardId. So now that we have our actions let's go ahead and look at our reducers, right because these actions but we passed to our reducers. So I'm going to open our reducers file and the very top producer we have here is the cards reducer. So let's go ahead and adjust this right now we just have a case for the ADD card action. But let's go ahead and add a case for the UPDATE card action. So when we update your card, what exactly do we want to do? Well, remember that we're doing this with immutability which means that that, when we return from this reducer, we're returning a brand new state object, instead of modifying our old state object. Now, the state object that we have here, in the cards reducer, is our array of cards state is that array. So what we can do to get a new array is say state.map and we're going to map over each individual card. Now we know that the card update that we want to make is action.data. In fact, what we could do is say let card update equal action.data. Now we will expect card update to have the id property so that we know which card to update, so, we can use that within state.map. We could say if card dot ID meaning the idea of the ID card we're mapping over here is equal to, and actually know it's safe it's not equal to card update dot ID then we'll just return that card unchanged. So, we'll return that card to our state object. Otherwise, if it is the card we're looking for, we'll do object.dotassign. We'll create a new object. We'll start by copying all the properties of the existing card onto that object, and then we'll copy card update on \to that object. So this way will update the one card that we want to update in our array, and then of course we'll return state DOT map. Now we can actually clean this up a little bit if we use a turnery expression. We could just say return if the ids are not equal. We'll just return the card. Otherwise we go ahead and return our object like this and I can put this on a new line to make it a little more readable. But then of course we could get rid of the return statement and also get rid of our parentheses here and tighten this up just a little bit more, and there we go. That's our producer for update card. Now we can also do case for delete card and this is going to be a little bit easier. We can just return stage dot filter which will create a new array, in we'll loop over each card and we will only return, where the c.id does not equal action.d. Because remember from our action we saw that action.d is going to be that card I-D. So this will reset our state so that it has all the cards except the one we want to remove. All right so that's our reducer now. Next we're ready to create the component for this, and as we know we've already created a card model that's going to do all the heavy lifting for our at model. The only thing we need to do is extend this from a representational component to be an actual container component. Let's go ahead and create a new component that we're going to EditCardModal.js. We don't need to import react here but we will import are the two action creators we just created, update card and delete card. And we'll get those from actions Oof course, we'll also import connect from react-redux. And finally, of course, we will import CardModal from CardModal. All right, next we need to create our binding functions. So let's create const mapStateToProps, and we're gonna use this function very similarly to how we used it in the previous lesson when we were doing visible cards. The first parameter here, we're only going to care about the cards property And from our router parameter, we're only going to care about params.deckId. And then in here, we're just going to return a single property and that is the card. Now remember when we did our new card model we created a new card object here. However, instead this time we're going to filter from cards. So we'll say cards.filter filter, and will filter on the card, and we're looking for where card down ID, is equal to card ID, and I just realized up here in the parameters I said we're looking for the deck ID. We're actually looking for the card ID property, right? Because remember, as we saw in her previous lesson, the road will have both the deck ID and the card ID, but we're really only interested in a card ID. Okay, so, we're filtering from our entire array of cards, and we're only gonna get the card where card.ID matches the card ID in the URL. However, that's going to return an array with one item. So, let's just do index of zero to get only the first item in that Ray. All right so now the next one constant map dispatched of props and you might remember from our card Motile lesson that there are two functions that we need here. The first one is on save and the second one is on delete. So first on save is going to be a function that will take our card, and we'll call dispatch from within this function, and we will call the update current action creator and we'll pass it the card. For on delete we'll take the card ID and will dispatch delete card and will pass it the card ID. Those are all the bindings that we need for our edit card model. So, let's go ahead and do export default. We'll call our connect function. We'll pass it mapStateToProps and we'll also pass it mapDispatchToProps. And then we can pass it the CardModal and now we have our EditCardModal. And what we've just done here really shows us the power of good presentational components. Some of your presentational components won't be that reusable they will be just one off items. However I think you'll find that in a large application. Many of your presentational components can be reused. Similarly to the way that we've reused the card model presentational component in this lesson, we're just about ready to see this in action, we just have to add R wrote. So let's go back to app.js and right now we have a wrote for the new card model. I'm going to duplicate that and we'll change the wrote path here to deck/:deckID/new. E slash edit slash colon card ID and the component that we're going to use is the EditCardModal, and then up here I'm going to duplicate my call to new card modal. And we'll import at it card model from components, /edit card modal. So let's see if this is working. We head back to our application here. I will select a deck. So we'll select one here and now we have our front card here and let's go ahead and click edit and it doesn't quite work. The U.R.L. changed but we got a new error. We cannot read property front of undefined, and let see this is within the card model where we're passing card in, so let's see did something go wrong there? If we come back to edit card model here we should be getting the card through map state to props here. I wonder if there's a problem with getting that card. Let's test this by going into card model and within a render function here let's go ahead and console.log the card. Okay, so if we come back here. The app of course automatically refreshes, because we made some changes and we are on the deck/ID/edit/ID route, and notice we do have undefined being logged to the console. So for some reason our card object is not being set. So let's see what we can do is extend this a little bit here we can actually make this a full function so that we could do some debugging from within it, and we'll have to add a return statement here, and then we can say console.log card.id and then cardId. So let's see what the two values that we're comparing are, and if we come back to the console. Okay, it looks like we are trying to compare numbers with strings. So this will be simple enough to fix. Let me just undo the debugging code I wrote and then we can just wrap card ID here in a call to parse it, and we'll make sure we make that a decimal number. Now if we come back, look at that, our app refreshed and we have our Edit Card motile. Notice it does say Edit Card at the top and now we have this delete button over here. So let's see if we can actually make some changes. I'll just make a change to the front of the card, and if I save this you can see that the modal disappears and the card actually changed. And if I refresh the page yep of course that's being saved to local storage as you would expect, this is working really well. We can go ahead and delete the card also and notice that the card is gone. Let's try this with something from deck two. If we go to deck two, we can change this to say for deck TWO, and save the card and there you go. Now if I hit Cancel, it will disappear without having made any changes. Excellent, in fact I could even make some changes here to the front of the card but if I click Cancel, those are not saved. So now we can properly edit cards. We can create cards. We're viewing them, we can edit them. And of course we can even delete them our application is getting pretty close to finished and the next lesson. We're going to add some filtering capability that will allow us to search through our decks of cards.