8. The useMutation hook
3m

💻 Mutation in client-land

Playing with the Explorer was fun, but we do need to run the from user input in our app. So let's move over to client land and send off our mutation using a new hook!

We want to update the number of views just before we navigate from the homepage to the track page. This navigation is happening inside our TrackCard component.

Inside the client/src/containers folder, let's open up the track-card.js file.

At the top, let's start by importing from the @apollo/client package. We'll need gql, because we'll be using that same string template literal for our , and we'll also need the useMutation hook to send our to our server.

import { gql, useMutation } from "@apollo/client";

Next, let's make a new to hold our called INCREMENT_TRACK_VIEWS, setting it to the gql template literal and adding backticks (`). Inside the backticks, we'll paste the we built previously in Studio, and add a comment to explain what this mutation is for.

/**
* Mutation to increment a track's number of views
*/
const INCREMENT_TRACK_VIEWS = gql`
mutation IncrementTrackViews($incrementTrackViewsId: ID!) {
incrementTrackViews(id: $incrementTrackViewsId) {
code
success
message
track {
id
numberOfViews
}
}
}
`;

🎣 The useMutation hook

Because this is a and not a , we won't be using the useQuery hook we're familiar with. Instead we'll switch to the useMutation hook.

Inside the TrackCard component, we'll start off by calling the hook. It takes in the we set up earlier, INCREMENT_TRACK_VIEWS, as the first parameter.

The second parameter is an options object with a variables key. Here, we'll add the incrementTrackViewsId and set it to the id of the track we're navigating to. This id has already been destructured for us at the top from the track prop.

useMutation(INCREMENT_TRACK_VIEWS, {
variables: { incrementTrackViewsId: id },
});

Now, here's a twist: unlike with useQuery, calling useMutation doesn't actually execute the automatically!

Instead, the useMutation hook returns an array with two elements, which we'll start to destructure here.

const [incrementTrackViews] = useMutation(INCREMENT_TRACK_VIEWS, {
variables: { incrementTrackViewsId: id },
});

The first element is the mutate function we'll use to actually run the later on. We'll call it incrementTrackViews. The second element is an object with information about the : loading, error and data. This component doesn't need it, so we don't have to extract it.

👆🏽Setting up the onClick

When do we want to run our mutate function? When the user clicks on the card!

Let's add an onClick prop to the CardContainer component and configure it to call our mutate function, incrementTrackViews.

<CardContainer
to={`/track/${id}`}
onClick={incrementTrackViews}
>
Sending a mutation client-side
We use hooks to send requests to our GraphQL API from a React client. To send a mutation, we use the
 
 hook. This returns an 
 
, where the first element is the
 
 used to trigger the mutation. The second element is an object with more information about the mutation, such as loading, error and 
 
. This hook takes in a
 
 as the first parameter. It also takes in an 
 
object as the second parameter, where properties like 
 
are set.

Drag items from this box to the blanks above

  • data

  • arguments

  • GraphQL operation

  • mutate function

  • options

  • useQuery

  • integer

  • useGqlQuery

  • array

  • useMutation

  • variables

  • values

Which of these are differences between the useQuery and useMutation hooks?

1️⃣ One more thing…

One last thing—let's add a console log to check the response when it's completed.

To do this, let's go back to where we set up our useMutation hook and add another property to our options object. The onCompleted property is a callback function that will run when the successfully completes, and it has access to the response that comes back. We'll log the response to the browser console.

const [incrementTrackViews] = useMutation(INCREMENT_TRACK_VIEWS, {
variables: { incrementTrackViewsId: id },
// to observe what the mutation response returns
onCompleted: (data) => {
console.log(data);
},
});

Our client app is ready to send off this to the server! Let's see the results of our journey in the last lesson!

Code Challenge!

Use the useMutation hook to send the ASSIGN_SPACESHIP_MUTATION mutation to the server. It takes two variables: spaceshipId and missionId. Destructure the mutate function (call it assignSpaceship), as well as the loading, error and data properties from the return array of the hook.

Previous

Share your questions and comments about this lesson

Your feedback helps us improve! If you're stuck or confused, let us know and we'll help you out. All comments are public and must follow the Apollo Code of Conduct. Note that comments that have been resolved or addressed may be removed.

You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.