We’ll use fetch and an async action creator to send a DELETE
request to the server and update the UI by removing the deleted item and displaying a success message once the save has completed successfully.
[00:00] Let's create a method to delete a todo on the server by duplicating the existing updateTodo method and modifying it. I'm going to rename this destroyTodo. Then I'm going to accept the ID as an argument, and I'm gong to update my URL to just use the ID that's been passed in from my endpoint.
[00:19] I'm going to change put to delete. I'm going to leave the headers as is, and I'm going to remove the body, because we don't need it. I'm also going to delete this extra then, because we're not concerned with the response. I'm going to save that file.
[00:34] With a service method in place, let's update our todo reducer and action creators. I'm going to start at the top of the file by adding that destroyTodo method to my imports. Then I want to scroll down and I want to create an async action creator for deleting a todo.
[00:50] I'll go under toggle todo, and here I'm going export a new constant, which I'm going to call deleteTodo. DeleteTodo is going to be a function that's going to accept an ID and that is going to return a new function that's going to accept dispatch as its first argument.
[01:14] The first thing I want to do is I want to use dispatch to display a message using my showMessage action creator. We'll just say removing todo.
[01:24] When I want to call that destroyTodo method that we just imported from the services, passing in the ID, and then I want to handle its response with a then. I'm not concerned with what comes back, as long as I get a valid response.
[01:37] I'm going to dispatch. Here I want call a new action creator that we'll create in a moment called removeTodo, and removeTodo is going to accept our ID. Let's go define removeTodo.
[01:49] I'm going to scroll back up to the top here, and I'm going to define a new action type constant. I'm going to export this, because I'm going to use it just like I'm using the rest of these to hide our message.
[02:00] I'm going to call this one todo_remove. That can just equal the string todoRemove. Down here, under replace todo, I'm going to export a new constant called removeTodo, and removeTodo is going to take in an ID, and it's going to return a new action object with the type todo_remove, and the payload is going to be our passed in ID value.
[02:32] Now that we have our action object defined, we can scroll down to the bottom and update our reducer. Just above default, I want to add a new case for todo_remove. Here we're going to return the state by spreading out the existing state, and then updating our todos again.
[02:57] I'll break this out into multiple lines. This time the todo is going to be the result of calling state with our existing todos, and then using the filter method to take in our todo and return it only if the ID does not equal the action.payload, which is our passed in ID for the todo that needs to be removed. We can save this.
[03:21] When we dispatch our async action creator to destroy the todo on the server, we start that process off by showing a message. I'd like to go into the message reducer, add todo_remove to my imports, and then I want to come down here and I want to update my reducer to also hide the message when todo_remove is dispatched. I can save that.
[03:48] Now all of our Redux code has been updated, and it's ready to go. We just need to wire this up to our UI. I'm going to open up todolist.js, where we're defining our todo list and todo item components.
[03:58] I'll start by adding deleteTodo to my imports from my todo file. With that imported, I'm going to scroll down to the bottom, where I'm calling connect on my top-level component.
[04:08] I want to add deleteTodo to my mapDispatchToProps. This will pass deleteTodo in the todo list component as a prop.
[04:20] Now I can use that to pass in to my todo item. I'll pass deleteTodo as a prop to todo item. Then that value is going to be this.props.deleteTodo.
[04:35] Now that we have that being passed into todo item, let's go ahead and use it. I'm going to scroll up to my todo item component, and I'm going to add deleteTodo to the argument destructuring. Then inside of my list item, I need to add some markup, so that we can add a button to click on to delete an item.
[04:55] I'm going to start with a span, and I'm going to give this a class name of delete-item. Then inside that span, I'm going to create a button and I'm to give that button an onClick, and onClick is going to equal a function that's going to call the passed in deleteTodo function, passing it the ID that I'm getting out of my arguments.
[05:22] I'm going to close the button. I'm just going to make the content of that button an X, and I'll save that.
[05:28] When the browser reloads, we'll see that each item now has a button next to it with an X in it. If I click on the X, it's going to delete that item. If I reload the page, we'll see that that's persisted, because it's actually deleting those items on the server.
[05:42] Now we have everything properly wired up and it works, but it doesn't look great, so let's open up app.css, and I'm just going to paste in some styles. All we're going to do is hide those delete item elements by default, show them when they're hovered over, and give a little bit of styling to each one of those buttons. I can save that.
[06:02] When the browser updates, we'll see that those Xs are hidden, but if I hover over an item, we get the X. If I click on the X, everything still works as expected.