Cache.evict does not retrigger query

Hi, I’m using useBackgroundQuery to aggregate data into a single query.
I have a structure like the following:

const FRAGMENT = gql`
  fragment ComponentXFragment on Query {
    myList {
      id
    }
  }
`

const ComponentX = ({ queryRef }) => {
  const { data } = useReadQuery(queryRef)

  const { data: { myList } } = useSuspenseFragment({
    fragment: FRAGMENT,
    from: data,
  })

  return <ul>{myList.map(({ id }) => <li>{id}</li>)}</ul>
}

const QUERY = gql`
  query PageQuery {
    __typename
    ...ComponentXFragment
  }
`

const Page = () => {
  const [queryRef] = useBackgroundQuery(QUERY)

  return (
    <Suspense fallback={null}>
      <ComponentX queryRef={queryRef} />
    </Suspense>
  )
}

Then I have another component that executes a mutation and invalidates the cache like this:

  useMutation(MUTATION, {
    update(cache) {
      cache.evict({ id: 'ROOT_QUERY', fieldName: 'myList' })
      cache.gc()
    },
  })

cache.evict correctly remove the field from the cache, but the query from useBackgroundQuery is not being re-executed. Using refetchQueries instead of cache.evict works.
Does useBackgroundQuery only execute the request on first render and then never trigger it again? But I’ve also tried with useQuery and the behaviour is the same.
How should I handle this? I don’t want to use refetchQueries because it requires to know every query name that uses myList. I just want to invalidate fields and let subscribed queries automatically refetch.

I tried the following and it seems to work, it’s still an “imperative” refetch but I don’t need to explicitly pass the name of the queries

        client.refetchQueries({
          updateCache(cache) {
            cache.evict({ id: 'ROOT_QUERY', fieldName: 'myList' })
            cache.gc()
          },
        })

What’s the difference between refetchQueries with updateCache and cache.evict?

What’s the difference between refetchQueries with updateCache and cache.evict ?

This is still not clear to me, there are many ways to manage the cache, but it’s not clear from the doc when each method is preferable over another.
In my view cache.modify is always better than writeQuery, updateQuery, etc.., as it’s not tied to a specific query structure, but is this view “correct”?

Starting from the start, if you have an active subscription (e.g. via useReadQuery), and that has a fetchPolicy of cache-first or cache-and-network, and not returnPartialData: true, you should see a refetch.

useSuspenseFragmenton it’s own wouldn’t cause that refetch though - maybe that might be the missing part here - I suspect you have fragment masking enabled, so the useReadQuery call doesn’t actually watch the value that is changing? :thinking:

As for cache.modify vs writeQuery, writeFragment etc. - there is no clear winner. I’d usually prefer writeFragment or writeQuery because it’s just closer to how the cache interacts with GraphQL naturally, but I don’t think there is a very specific technical reason for it.