Overview
Explorer proved the mutation works. Next we'll send it from the React app when a user clicks a track card.
In this lesson, we will:
- Define the
INCREMENT_TRACK_VIEWSmutation on the client - Call the
useMutationhook and destructure its mutate function - Trigger the mutation from a track card click and log the result
💻 Mutation in client-land
Playing with the Explorer was fun, but we do need to run the mutation 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 what we need. We'll pull gql from @apollo/client, and the useMutation hook from @apollo/client/react to send our mutation to our server.
import { gql } from "@apollo/client";import { useMutation } from "@apollo/client/react";
Next, let's make a new variable to hold our mutation called INCREMENT_TRACK_VIEWS, setting it to the gql template literal and adding backticks (`). Inside the backticks, we'll paste the mutation 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) {codesuccessmessagetrack {idnumberOfViews}}}`;
🎣 The useMutation hook
Because this is a mutation and not a query, 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 mutation 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 variable 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 mutation 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 mutation later on. We'll call it incrementTrackViews. The second element is an object with information about the mutation: 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.
<CardContainerto={`/track/${id}`}onClick={incrementTrackViews}>
1️⃣ One more thing…
One last thing—let's log the mutation response when it completes.
In Apollo Client 4, useMutation no longer accepts onCompleted or onError callbacks. Instead, the mutate function returns a Promise, so we can await it (or use .then) and log the result there.
We'll create a small click handler that runs the mutation and logs the returned data:
const handleTrackClick = async () => {const result = await incrementTrackViews();console.log(result.data);};
Then, pass that handler to the card's onClick prop instead of calling incrementTrackViews directly:
<CardContainer to={`/track/${id}`} onClick={handleTrackClick}>
Code review
Practice
loading, error and Drag items from this box to the blanks above
mutate function
arguments
optionsGraphQL operation
integer
values
variablesuseGqlQuerydataarray
useQueryuseMutation
useQuery and useMutation hooks?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.
Up next
Our client app is ready to send off this mutation to the server! Let's see the results of our journey in the last lesson!
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.