How to Update GraphQL Data in React

Updating data in a React application using GraphQL is primarily achieved through mutations. This article provides a straightforward guide on how to implement GraphQL mutations using the Apollo Client library, covering how to define the mutation query, utilize the useMutation hook, and keep the user interface in sync with your backend database via cache updates.

Define the GraphQL Mutation

To update data, you must first define your mutation using the gql template literal. This mutation specifies the input arguments required for the update and the fields you want the server to return once the operation is complete.

import { gql } from '@apollo/client';

const UPDATE_USER = gql`
  mutation UpdateUser($id: ID!, $name: String!) {
    updateUser(id: $id, name: $name) {
      id
      name
    }
  }
`;

Execute the Mutation in a Component

Apollo Client provides the useMutation React hook to trigger mutations. This hook returns a trigger function (which you call to run the mutation) and an object representing the execution state, such as loading, error, and data.

import React, { useState } from 'react';
import { useMutation } from '@apollo/client';

function UpdateUserForm({ userId }) {
  const [name, setName] = useState('');
  const [updateUser, { loading, error }] = useMutation(UPDATE_USER);

  const handleSubmit = (e) => {
    e.preventDefault();
    updateUser({ variables: { id: userId, name } });
  };

  if (loading) return <p>Updating...</p>;
  if (error) return <p>Error: {error.message}</p>;

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="Enter new name"
      />
      <button type="submit">Update Name</button>
    </form>
  );
}

Keep the UI in Sync

After performing an update, you must ensure the React application reflects the changes. There are two primary methods to handle this:

1. Automatic Cache Updates

If your mutation returns the updated object along with its unique identifier (such as id or _id) and the modified fields, Apollo Client automatically updates the corresponding item in its normalized cache. Any components rendering that data will automatically re-render with the new values.

2. Refetching Queries

If the update affects data structures that Apollo cannot automatically match (such as inserting into or deleting from lists), you can use the refetchQueries option. This forces Apollo Client to re-run specified queries to fetch the latest server state.

const [updateUser] = useMutation(UPDATE_USER, {
  refetchQueries: [
    'GetUsersList' // Name of the query to refetch
  ],
});