Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Map query result to another query's cache #706

Closed
migueloller opened this issue Sep 25, 2016 · 13 comments
Closed

Map query result to another query's cache #706

migueloller opened this issue Sep 25, 2016 · 13 comments
Milestone

Comments

@migueloller
Copy link

migueloller commented Sep 25, 2016

I'm using Apollo to build a production React Native app and I'm super grateful for all the great work you guys have done. Kudos!

There are a couple of things that I think could improve and I know many of them are already in the works (e.g., reimplementing loading logic in react-apollo and restructuring the design around fragments in apollo-client). It's super annoying that loading can be undefined sometimes and it's impossible to work with fragments so I'm looking forward to those changes!

There is another improvement that I wanted to mention because I'm not sure if it is in the works and I would love apollo-client to have something like it.

Imagine you have the following 2 queries:

query ($userId: ID!) {
  user(id: $userId) {
    name
    email
    posts {
      edges {
        node {
          title
          createdAt
        }
      }
    }
  }
}
query ($postId: ID!) {
  post(id: $postId) {
    title
    createdAt
  }
}

If the second query returns a post that would've been included in the users's post from the first query, there should be no network request. Currently with apollo-client, because they're different queries, the cache doesn't know any better.

I propose that we add an option to ApolloClient, similar to dataIdFromObject, called queryIdFromObject (this name is probably a bad one) that will let you map the result of a query to another query's key in the internal Redux store, with the purpose of improving the cache.

Here's how the option would be used for the example above:

const client = new ApolloClient({
  queryIdFromObject: ({ __typename, id }) => `$ROOT_QUERY.${__typename}:${id}`,
});

Potentially, this option could only be allowed for the root query (I don't see it being beneficial elsewhere) and dataIdFromObject could be used internally so that the code above could be simplified to:

const client = new ApolloClient({
  // maybe this name is better?
  rootQueryNameFromObject: ({ __typename }) => singularize(__typename.toLowerCase()),
});

Regardless, this would greatly reduce the number of trips to the API that the app needs to make.

Thoughts?

EDIT: If the server is Relay compatible, then it would be even simpler because the relevant root query would be node and/or nodes

@tmeasday
Copy link
Contributor

tmeasday commented Sep 27, 2016

This is an interesting idea; maybe instead of mapping a query to a part of another query, instead we should have a mechanism to map to a data id -- so dataIdFromField or something like that.

So in this case, we'd say "the root field post with variable id=X should map to the object with id='post:X'". I'm not sure what the API for that should look like.

@tmeasday tmeasday added the idea label Sep 27, 2016
@migueloller
Copy link
Author

@tmeasday,

Yes, that would be a nice way to go about it. Here are 2 possible APIs that we could think about:

  1. Add updateQueries to the options in client.query
  2. Define a map in the client constructor that will map some result object (internally it will probably use its data id) to some query (most likely the root query) or some variation of this
    • This is what we've been discussing so far
    • The API could look similar to the 2 examples I have above.

Which of the 2 seems more natural? Should we expand on one over the other or should we expand on both and see which API makes the most sense?

@stubailo stubailo mentioned this issue Sep 29, 2016
@stubailo stubailo added this to the New API/Refactor milestone Sep 29, 2016
@stubailo
Copy link
Contributor

This is now implemented! #809 Just some tests to do.

@stubailo stubailo mentioned this issue Oct 19, 2016
13 tasks
@migueloller
Copy link
Author

@stubailo,

Thanks so much for implementing this! Would you mind posting a quick snippet of how the new API could be used to solve the issue mentioned above?

@fikriauliya
Copy link

Great! Having this issue as well, the PR would reduce my app's network traffic dramatically. 👍

@stubailo
Copy link
Contributor

Hoping to get this done and documented before the end of the week! Things have been very busy around here because of the GraphQL Summit.

@helfer helfer modified the milestones: Release 0.5, Post 0.5 Oct 26, 2016
@migueloller
Copy link
Author

It looks like this is now documented here. Thanks for all the hard work!

@helfer
Copy link
Contributor

helfer commented Nov 17, 2016

Implemented in #921

@migueloller
Copy link
Author

Looking again at the original use case presented in the originating issue description, it doesn't look like result reducers solve this problem because the post query has a changing variable (id) and result reducers don't have a way to map the post(id: $postId) back to the internal dataId that the store uses.

@helfer
Copy link
Contributor

helfer commented Dec 16, 2016

@migueloller I'm not sure I understand what result reducers have to do with cache redirects?

@migueloller
Copy link
Author

@helfer, originally I believed that result reducers would solve the issue I mentioned above in #706 (comment). It looks like it's more of a cache redirect issue (as you say). Should a separate issue be opened or this same on reopened (and maybe the title changed)?

@helfer
Copy link
Contributor

helfer commented Dec 16, 2016

@migueloller Have you looked at #921? I think that should do what you need.

@migueloller
Copy link
Author

@helfer, ahh yes... Just read the docs. I initially thought #921 was for result reducers. Sorry about that! 😅

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 17, 2023
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

5 participants