Let's start by creating a function that will save a new todo to the server. Since we'll be making a call to the same API endpoint as getTodos, I'm going to duplicate it, and then make some changes.
We'll start by renaming this createTodo, and then we need to take an argument, which is going to be the name for our todo. Then we're going to make fetch call and we're going to return that promise. Since we're going to make this call a post, we're going to pass in an object with some options.
The first option here is going to be the method, which is going to be post. Then I'm going to paste in some headers, and then we need a body for our request, and we want to pass a todo object. We're going to JSON.stringify, and we're going to create an object inline.
It's going to have a name property, which is going to be the name that's been passed in to our createTodo faction. Then we're going to default the isComplete flag to false. That gives us everything we need to make our API call to create a new todo on the server, so we can save this file.
Now we need to make some changes to our reducer file. Open up todo.js. If we look at our reducer, we're already set up to add a new todo to our list, but we don't have an action creator for it. Let's add that. Up here, under my loadTodos action creator, I'm going to export const addTodo.
This is going to be an action creator function that's going to take a todo object, and then it's going to return an action object with the type todo_add and a payload using the todo that's been passed in. We also need an action creator to call our API.
Let's scroll down here under fetch todos and let's add another action creator, which I'm going to call saveTodo. SaveTodo is going to take the name for our todo, and, because this is an asynchronous action creator, we're going to return a function that receives dispatch as an argument.
Here we're going to call our createTodo method, passing the name, and then we're going to handle the promise that's returned. In this case, we're going to take the response, which is going to be our newly created todo object, and we're going to use our dispatch function to pass our todo to the addTodo action creator.
The last thing we need to do is pull this createTodo function in. I'm going to scroll up to the top, where I'm importing getTodos, and I'm going to add an import for createTodo. Now that the action creators have been set up, I'm going to save this file, and I want to jump over to the todo form component.
I'm going to need to make a couple changes here. I'm going to start by adding an import for the saveTodo action creator that we just set up. Now, I'm going to scroll down to the bottom of the file, where I'm making a call to Connect.
I want to update the mapDispatchToProps to also include saveTodo. This'll make that saveTodo action creator available on props in my component. Now I'm going to come up to the top. I want to refactor this component.
Right now, it's a stateless functional component. We had this handleInputChange function being created on every render. We're going to need to add another one to handle the submit, so I want to make these instance methods of a class.
I'm going to come up here and I'm going to update my import from React to also import Component. Down here, I want to change todoForm to be a class, which extends Component. Now that this is a class component, we're going to give it a render method.
I'm going to take everything we have here and move it into the render method and I can clean up this whole function. Here we're destructuring props, and that's just going to change to this .props, and then handleInputChange right now is being defined inside of render. I want to make that a class method.
I'm going to take that and I'm going to move that up and get rid of the const keyword. Then I'm going to refer to that down here as this.handleInputChange. Now, updateCurrent is coming from this.props, and we're no longer using it inside of render, so we can take that out of there.
Now, we need a submit handler for our form. I'm going to come up here and I'm going to define handleSubmit, and that's going to be an error function that'll accept an event. I'm going to call event.eventDefault. When the form is submitted, I want to call saveTodo.
SaveTodo is passed in through Connect and is now part of the props on this component, so I can call this.props.saveTodo. I want to pass it the current todo, so I'll grab that off the props, as well.
Now that we have handleSubmit defined, let's attach it to our form by giving the form tag down here an onSubmit property, and passing it this.handleSubmit. With that in place, let's save this. We'll let the browser reload, and now we can try submitting a new todo.
We'll see that our new todo shows up. When we reload the page, it should be loaded on the initial fetch from the server. When we submitted the new todo, it was saved to the server and it showed up in our todo list, but our todo form was not cleared out.
We can fix this easily by going back to our reducer, and in the handler for our todo add action, all we have to do is update the current todo value to be an empty string. If I save this, we can go back into the browser.
We can submit another todo, and this time it's added to the list, our form is cleared out, and, again, if I reload the page, we can confirm that this has been saved to the server, because it's loaded on the initial fetch.