Search code examples
apolloreact-apollo

Invariant Violation error when updating apollo cache after mutation


I try update my list after item remove by this article

but get Invariant Violation error.

my mutation:

const deleteFn = useMutation<FeaturedPlaylistGroupDelete, FeaturedPlaylistGroupDeleteVariables>(deleteQuery, {

    update: (cache, mutationResult) => {
      console.log('mutationResult', mutationResult)
      const data = cache.readQuery({ query: featuredPlaylistsGroupsQuery })
      console.log('cache', cache)
      console.log('cacheData', data)
      cache.writeQuery({
        query: featuredPlaylistsGroupsQuery,
        data: data.filter((item) => item.id !== mutationResult.data.featuredPlaylistGroupDelete.id),
      })
    },
  })

featuredPlaylistsGroupsQuery:

export const featuredPlaylistsGroupsQuery = gql`
  query FeaturedPlaylistGroups(
    $active: Boolean
    $noCategory: Boolean
    $dateFrom: String
    $dateTo: String
    $title: String
    $regions: [String!]
    $categories: [String!]
  ) {
    featuredPlaylistGroups(
      active: $active
      noCategory: $noCategory
      dateFrom: $dateFrom
      dateTo: $dateTo
      regions: $regions
      title: $title
      categories: $categories
    ) {
      active
      category {
        title
      }
      datetime
      id
      region
      title
    }
  }
`

deleteQuery:

const deleteQuery = gql`
  mutation FeaturedPlaylistGroupDelete($id: String!) {
    featuredPlaylistGroupDelete(id: $id) {
      active
      categoryId
      category {
        title
      }
      datetime
      id
      region
      title
    }
  }
`

error:

Invariant Violation: Can't find field featuredPlaylistGroups({}) on object { ...


Solution

  • When you use readQuery, what's returned is what would have been returned in the data part of the response for that query. This is always an object. So for a query like

    query {
      foo
      bar
    }
    

    You get an object like

    {
      "foo": "FOO",
      "bar": "BAR"
    }
    

    When you call readQuery using your featuredPlaylistsGroupsQuery, you'll get an object with a single property named featuredPlaylistGroups. So your code should look more like:

    const cached = cache.readQuery({ query: featuredPlaylistsGroupsQuery })
    const featuredPlaylistGroups = cached.featuredPlaylistGroups.filter(item => {
      return item.id !== mutationResult.data.featuredPlaylistGroupDelete.id
    })
    const data = {
      ...cached,
      featuredPlaylistGroups,
    }
    cache.writeQuery({
      query: featuredPlaylistsGroupsQuery,
      data: data,
    })
    

    However, this still will not work because featuredPlaylistsGroupsQuery takes a number of variables. We need those variables in order to read and write from the cache, since each combination of variable that has been queries is stored separately in the cache. So you will either need to keep track of the variables used and call readQuery/writeQuery on all used combinations, or use something like apollo-link-watched-mutation