In this lesson we'll see how to easily make GraphQL mutation using the Apollo useMutation hook. Same as before, we get access to any data the mutation returns, as well as loading and error states.
Instructor: [0:00] I added a View button to each one of the notes. When you click on the View button, it routes to this new URL at the top that points to specific note's ID. This message appears at the side, to tell us that we're looking at that note. This changes as we click on the different View buttons.
[0:18] Why do we change the URL? If I want to send a note to some friend, I can just send them this URL. When they open up the app, it's going to open up at that note directly.
[0:28] In terms of how this is built, in my NotesList component, I just added this View Note button component as a child of UINote. I wrapped it inside this React RouterLink component, which is the one responsible for changing the URLs at the top, so that they match the note ID that I clicked on.
[0:48] Now, in the AppLayout component, I'm displaying an EditNote right next to my NotesList stack. This EditNote component will only be shown when the URL route matches this specific format. All my EditNote component currently does is it extracts the note ID from the URL params, and then just renders this message.
[1:13] My server has a separate query that allows me to get a specific note by its ID. I'll start building this out, import the GraphQL tag, and I'll except the ID of the note as a variable to this. The exclamation mark at the end makes it a required variable. I'll query the backend for a specific note by passing it the ID that I need. From that note, I'll only need the ID and the content.
[1:44] I'll use it in my component. I'll need to pass in an ID variable, pointing it to my note ID from the URL params. I'll extract the data from the response, and then I'll return this UIEditNote component, which I had ready from before.
[2:01] This component displays whatever note I pass it in as a prop, and because my data object matches my query up here, that means that if I have data, there should be a note on it.
[2:13] Back in my browser, if I click between notes now, I get the note's full text displayed here. If I refresh the page, and I slow down the network and I click on some of the nodes, we're currently not handling Clothing states, but we can see that it takes a while for the note to load and display.
[2:32] Once I load a few, I can then click back through them, and they're just going to load instantly, even though I'm on a really slow network. Apollo's cache works with this scenario as well. The reason we built this whole component is so we can edit a note, and then save whatever content we have in this box, back to the server.
[2:52] Let me add the useMutation hook this time so we can persist changes to the data. I'll import it from Apollo Client up here. Then, I'll start writing my mutation inline. I'll call my mutation updateNote. I'll need to give it the ID of the note I'm updating, and the new content.
[3:11] Then, I'll fire off the updateNote mutation, which my server accepts, by passing it again the ID and the content from my variables.
[3:21] Similar to the useState React hook, this gives me back an array on which I can destructure the updateNote function. This is a function that, when called, it's going to invoke my mutation. My EditNote component has an onSave prop that gets called whenever I press the Save button.
[3:39] I'll pass it a callback that will be invoked with the new content of my note. I'll call my update function, which will accept some options. Here's where I can pass any variables I want to my mutation. I'll pass it my note ID and the new content. These variables in here need to match the ones I defined in my query up here.
[4:00] Back in my browser, if I make an edit and press Save, I'll get some errors. I can see my retry logic kicking in and retrying a few times. If I look at the problem, it's saying, "Field updateNote must have a sub-selection of fields."
[4:19] Interesting. Mutations can actually return stuff, same as queries. That error is telling me that I need to tell GraphQL what to return from this mutation. One of the fields I can return is whether it was successful or not. I'll make the edit again, press Save, and this time it looks successful.
[4:38] If we look at the request, I can see it gets passed my new content and the note ID as variables. It responds with some data that contains the name of my mutation and my successful status. If I refresh the page, I can see the edit stays on there, and it's also reflected here. It worked.
[4:57] When doing mutations, I also get an optional object in here that gives us data, loading and error states. We can, of course, put all three of them to good use. In this case, let's quickly just try out the loading, which I'll send to the isSaving prop of our EditNote component. If I now slow down the network, I make another edit and I press Save, I'm now handling loading states.