DEV Community

loading...
Cover image for Avoiding refetch to update Apollo Client cached data (React)

Avoiding refetch to update Apollo Client cached data (React)

endoooo profile image Eric Endo ・2 min read

TLDR

Include updated fields in mutation response: Apollo will do their magic 🪄 and update the cached data. No need to refetch().


If you use Apollo Client (with hooks please!) in your React project, chances are that you have already done something like this to update the data after a mutation:

const GET_POST = gql`
  query GetPost($id: ID!) {
    post(id: $id) {
      id
      title
      description
    }
  }
`

const UPDATE_POST = gql`
  mutation UpdatePost(
    $id: ID!,
    $title: "String,"
    $description: "String"
  ) {
    updatePost(
      id: $id,
      title: "$title,"
      description: "$description"
    ) {
      id
    }
  }
`

function PostDetails({ id }) {
  const { data, refetch } = useQuery(
    LIST_POSTS,
    { variables: { id } }
  )
  const [updatePost] = useMutation(UPDATE_POST)

  async function editPost(formValues) {
    await updatePost({ variables: formValues })
    refetch() // <-- do we really need it?
  }

  // ...render and other component parts
}
Enter fullscreen mode Exit fullscreen mode

Can we avoid the refetch() after updatePost() (thus avoiding one unnecessary request)? Yes, by simply adding some fields to the mutation return:

const UPDATE_POST = gql`
  mutation UpdatePost(
    $id: ID!,
    $title: "String,"
    $description: "String"
  ) {
    updatePost(
      id: $id,
      title: "$title,"
      description: "$description"
    ) {
      id
+     title
+     description
    }
  }
`
Enter fullscreen mode Exit fullscreen mode

Why does this work? To answer this, we need to understand two Apollo concepts first: data caching and cache updating.

For the caching part:

Apollo Client stores the results of its GraphQL queries in a normalized, in-memory cache. This enables your client to respond to future queries for the same data without sending unnecessary network requests.

For the updating part:

In order for Apollo Client to update the cache automatically, we have to remember to always return the new data in operation responses.

For query responses, that’s the point. The entire purpose of a query is to return data and cache it.

But for mutations, like editTodo that change a single entity, we should be able to update the item automatically if we return the value in the mutation response.

So, for mutations like this one from the example (a single entity with id), just include updated fields in the mutation response: Apollo will do their magic 🪄 and update the cached data. No need to refetch().


But... what about other cases, when entities have no id field or mutations that change data related to the updated entity, for example?

This Apollo Blog post (already linked in the updating part) talks about some strategies for those cases - but we can talk more about those cases in one (or more) post(s) in the future.


PS 1: English is not my native language. Feel free to suggest any corrections, point grammatical errors, and etc.

PS 2: check the original post here (in Brazilian Portuguese)


Cover background image by SpaceX

Discussion (0)

pic
Editor guide