The term "upsert" means to support both inserting a new record and update an existing record. In order to support upsert capabilities with a form in React, we need to determine which mode we're in and if we're performing an update, we need to make sure the form fields are populated the existing values for the item being updated. In this lesson, we'll refactor an exiting form to handle updates and verify that we've also maintained the ability to use that same form component to insert new records.
Instructor: [0:00] I've updated the service module and now save card determines whether it's going to call create card or update card based on the presence or absence of an ID on the card object that gets passed in.
[0:11] Create card will take our card object with our term and definition and make a post request that we already had set up. Update card will call the endpoint with the card ID appended to the URL using the put method to update an existing card.
[0:25] Now let's refactor our card form component. Let's start by accepting a card object as a prop. Right at the top of this function I'm going to define a constant called ID and that's going to check for the presence of card. We'll also check to make sure that it has an ID property on it. If both of those are true, we'll assign card.ID to that ID, otherwise we'll make it explicitly undefined.
[0:54] In the case that we do have an ID, we know we have a fully formed card object, so I want to come in here. I want to set the initial value of term and definition based on the passed in card. We're going to use a ternary based on ID. If ID exists, then term will start with whatever the value of card.term is and otherwise it will be our empty string.
[1:18] Then we can do the same thing down here for definition. Check for ID, card.definition, otherwise empty string. This will run just on the first render and it will set our initial state for the form inputs to the card values if a card has been parsed in.
[1:36] Let's go down to our JSX and right above the form I want to add a heading that indicates whether you're adding a card or updating an existing card. I'll add an H4 and then inside the H4 we're going to use that same ternary with the ID again and we're going to pass the expression update card if there's an ID and add card if there's not. We'll save that.
[2:04] With that in place I'm going to scroll up and I want to find where we call save card and I want to just give this the ID value. That will go through as undefined if this is for a new card. This will tell our service functions here whether or not to call update card or create card.
[2:26] Let's go to card preview. We need to take this card that we're receiving here and pass it into our card form. I'm just going to make this a prop called card and I'm going to pass it directly in. This prop is just the card object. We're not spreading it because we're not destructuring it or using the rest operator on the other side. Just pass it in whole and we'll save that.
[2:46] Let's switch to the browser. I should still be able to add an item. Let's just make sure that this refactor hasn't broken our insert functionality. We'll see we have our heading here. I'll save and then I'll add the card. It'll clear it as we expect.
[3:03] Now if I take one of these other cards and I hit edit, when we switch to card view, we should see our update card heading. We should see our sample data. I'm just going to update this. I'm going to save it. I'm going to reload. We'll see that the update made it to the server, but the UI didn't update like we would have expected. Let's fix that.
[3:24] I'm going to go into app.js and I'm going to add a function to the top of this component and I'm going to call it handle update. Handle update is going to receive a card and we're going to use set cards again and we'll get the existing cards. Then we'll return our new cards.
[3:45] We'll get our new cards by mapping over the existing cards. Then for each card we'll see if its ID matches the card.ID from the parsed in card. If so, we'll return that new card that's been updated. Otherwise, we'll just return the existing card that we're getting here as C.
[4:09] In order to use this, I'm going to take this handle update and I'm going to pass it down to my card preview component as a prop that we'll call on update. Then back in card preview, we're going to accept on update as a prop and then we're going to pass it through to card form as card forms on save.
[4:36] Card form has this on save that it calls after it successfully made its API request. In this case we'll have it call on update. I'll save that. Let's go back to the browser. I'm going to click edit on this same sample. We'll do update number two. We'll save it. We'll see that this time it re-renders with the updated value.