apollo-feature-requests icon indicating copy to clipboard operation
apollo-feature-requests copied to clipboard

Feature request: partial data

Open jantorestolsvik opened this issue 6 years ago • 5 comments

Migrated from: apollographql/apollo-client#2425

I found multiple issues mentioning a feature i would like

https://github.com/apollographql/apollo-client/issues/2977 https://github.com/apollographql/apollo-client/issues/2872

What I would like is a way to only fetch the fields which are not present in the cache. For me the problem is a bit different from the other issues i linked to. My main problem is that i fetch a lot of data when doing mutations, and then a component will mount right after which will query for the same data (because i can get to this component either by doing the mutation, or by going there directly). The issue then is that I cannot have other data in the query, because that would trigger a refetch of the whole data structure. I could split it up into multiple queries, but it would be easier with a nice way to do it.

For example, say I have a mutation startTask { task {...} }

and after i have started the task I am sent to that taskpage. There I do a query

query GetDataForTask { task(id:123) username }

Now if I do the mutation startTask first the GetDataForTask query will fetch the task all over, because of the username

There has been proposed multiple ways to solve this, and it seems this was once part of apollo too. I have not found a favorite, but has there been any work on this since?

jantorestolsvik avatar May 19 '19 20:05 jantorestolsvik

This is a really interesting idea, having to split the query into multiple queries can lead to more roundtrips for only a few fields and also it makes the queries/code more complex.

ignacio-chiazzo avatar Oct 30 '19 14:10 ignacio-chiazzo

I would also really appreciate a feature like this. My situation is the following. I'm fetching a list of documents with file name, status and some other fields. When you click on it a more detailed view opens. Which displays the file name and status in the header. The rest of the data has to be fetched then. I would like to be able to re-use the file name and status for the header while the rest is loading. I tried setting returnPartialData to true but this doesn't give the desired result since all these fields are defined as non-nullable in the schema. Now I have to pass the information that should be shown in the header to my component which itself fetches the additional information of the same document which feels quite wrong.

levrik avatar Mar 10 '20 08:03 levrik

Yeah, I have a similar use-case here. I'm showing breadcrumbs on every page in my app. The name of the first element in the breadcrumbs is based on a slug in the URL which is resolved as part of the query that runs on every page. I've essentially got a specific query with a specific fragment in it that is always run on each page to ensure the data is there - but of course because the data is grabbed every page load the first time if the whole query isn't in the cache, I have to show a loading indicator between pages (and they could move moving between pages by interacting with these breadcrumbs, so that'd be particularly jarring).

returnPartialData does work, but when using TypeScript, the generated types are basically lies because then any of the top-level queries can be null. I'm not entirely sure what the solution is, maybe some way of batching up 2 "separate" queries into one request, then splitting the result back out so you can cache separately, but only query once?

seeruk avatar May 01 '20 16:05 seeruk

My case is a bit simpler but still requires partial data.

I believe readFragment and writeFragment are often combined to update the cache. The throwing of readFragment when one or more fields are missing, makes it harder to deal with cache updates. Having a partial flag here would be most welcome.

const fragment = gql`
  fragment BlogComments on Blog {
    _id
    comments {
      body
    }
  }
`;

const newComment = { body: 'hi' };

const blog = store.readFragment({ 
  id: 'blogId', 
  fragment: fragment,
});

const nextBlog = Object.assign({}, blog, {
  comments: [...(blog.comments || []), newComment],
}

store.writeFragment({
  id: 'blogId',
  fragment: fragment,
  data: nextBlog,
});

If blog here does not yet contain the comments property in the cache, this will fail due to the error that readFragment is throwing. Which is unfortunate. if readFragment would return null or Partial<T>, it would become less cumbersome to deal with this kind of scenario.

smeijer avatar May 20 '20 13:05 smeijer

This might help: https://github.com/appmotion/apollo-augmented-hooks

dylanwulf avatar Jul 04 '21 15:07 dylanwulf

voting for the feature, as it is important in BFF use case for Apollo Server

VadimZhiltsov avatar Dec 06 '22 10:12 VadimZhiltsov