Skip to content
This repository has been archived by the owner on Jul 6, 2020. It is now read-only.

Should updateQuery always return partial results? #140

Open
mgrip opened this issue Dec 17, 2019 · 2 comments
Open

Should updateQuery always return partial results? #140

mgrip opened this issue Dec 17, 2019 · 2 comments

Comments

@mgrip
Copy link

mgrip commented Dec 17, 2019

I'm still learning the details of graph cache - so forgive me if some of my assumptions are incorrect

Currently, I believe the updateQuery function uses the same cache result policy as normal queries - which from the docs is: When the cache has enough information so that only optional fields in a given query are missing, then it delivers a partial result from the cached data. My question is - when we are updating cache after a mutation, would it make sense to always return partial results, even of some of the missing fields are required? Here's my use case:

A mutation causes a side effect, that we need to manually update in the cache. Lets say something like this:

const QueryOfAllDataEffected = gql`
  query _($listId: ID!) {
    __typename
    list(id: $listId) {
      __typename
      id
      fieldEffectedByNewTodo {
        __typename
        id
        ...
      }
      todos {
        __typename
        id
      }
    }
  }
`
createClient({
  ...,
  updates: {
    Mutation: {
      addTodo: (result, args, cache) => {
        cache.updateQuery(
          {
            query: QueryOfAllDataEffected
            variables: { listId: args.listId }
          },
          data => {
            ...
          }
        )
      }
    }
  }
})

After the mutation is done, 2 things need to be updated. 1) add the new todo item, and 2) update the "fieldEffectedByNewTodo". However, in the actual application there might be several different queries referencing these same fields (this is the benefit of using graph cache), but we have no guarantees of which ones have been accessed. So even though both are required, its possible that we only have one in the cache so far. What I'd like to do is to be able to check if either "fieldEffectedByNewTodo" or "todos" is already in cache, and manually update whichever ones are. And if either is not already in cache - just leave them as "null" so that they will be fetched whenever a query tries to access them. The problem is that since both todos and fieldEffectedByNewTodo are required, data will always be null unless both have already been queried and are in cache.

Sorry I know that's probably not the best example, but hopefully I got my point across. Maybe there's a better way to be updating the cache that I'm just missing? Thanks!

@mgrip
Copy link
Author

mgrip commented Dec 17, 2019

I also considered using writeFragment, but that doesn't give you access to the value that's currently in cache. Maybe I could try using a combination of readFragment to get the current value of a field from cache, and if it exists using writeFragment to update it?

something like

const currentList = cache.readFragment(
  gql`
    fragment _ on List {
      id
      todos {
        id
      }
    }
  `,
   args.listId
);
cache.writeFragment(
  gql`
    fragment _ on List {
      id
      todos {
        id
      }
    }
  `,
  {
    id: currentList.id,
    todos: [...currentList.todos, result.todo]
  }
);

...and then the same thing for the other field?

(side note - the documentation I think needs to be updated from updateFragment to writeFragment)

@kitten
Copy link
Member

kitten commented Dec 19, 2019

would it make sense to always return partial results, even of some of the missing fields are required?

That's a good point! I'm not quite sure about this one. The problem is that we'd like to enforce that data returned from Graphcache is always compliant to the schema, so missing fields aren't just returned so that the data matches up with generated types (e.g. for TypeScript)

I can see your problem in this case though, as it's inconvenient to add to a query that isn't complete in the cache. 🤔

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants