Closed dustinfarris closed 7 years ago
I don't understand what the cachedItem
is doing. why not just return the value of item
?
As a rule of thumb, @cached
should only be used in 2 cases:
@live
data with a standard query. @mattkrick if i enter the site at the index route, this query hits the server:
items {
id
name
}
when i click an item and go to the detail route, this query hits the server:
item(id: $item_id) {
id
name
}
but i don't see why that should hit the server when i already have the Item from the "items" query in the index. so i'd like to use the cache there
but, if the user enters the detail route directly via URL, then there is no cache because they never visited the index page. so i actually need to hit the server in that instance.
mattkrick you've said before that cashay will only ask for what it doesn't have, but this doesn't seem to be the case across different Operations, even when the underlying Type is the same.
Item
and GraphQLList(Item)
you're asking for items
and then you're asking for item
. How does your cache know that item is a subset of items? Couldn't it be something completely different?
We could assume that the unique mix of type & id will always return the same result, but GraphQL doesn't make that assumption, so i'm hesitant to make cashay assume it. In the real world, for the detail view, you'll want extra fields that weren't supplied by items
. That means a network request is unavoidable. If you have to make a network request, is the added complexity in your app worth the extra 50 bytes for the name
field?
that's not to say we can't improve on the pattern. Write a query that makes sense to you, we'll poke holes in it, & then we can make cashay support it.
right, so in my case i'm designing for desktop and mobile, so when the user goes to the detail page, i'd like to have "name" already up there in the header while the network request resolves for everything else. I think there is a clear win for me in leveraging cashay's client cache if I can figure out how to make it work for me.
You're absolutely right that I'm going to want more data in the detail route.
Here's what I'm actually doing (or rather want to do):
Index route:
maps {
id
name
}
Detail route
map(id: $map_id) {
id
name
categories {
id
name
}
}
The fields will grow as my app grows, but that's the gist.
Now cashay knows my schema. Cashay should know that the map
field on my rootQuery returns a Map
type. Cashay should know that the maps
field on my rootQuery returns a list of Map
type. I'm not sure I follow what you're saying with regard to GraphQL (and Cashay) not assuming that a id/type pair is unique? It seems to me that I've laid that out pretty explicitly in my schema—or maybe this a deeper subject than I'm aware.
Perhaps the item
I'm asking for wasn't included in the items
result for whatever reason. Well that just means it's not in the cache so we're making a server request for everything after all, right?
So maybe there's two options:
Option 1 Leverage cache implicitly all the time
so assuming I've hit the index route already, in my detail route I do:
cashay.query(mapDetailQuery, variables: { map_id });
cashay sees that it has a record for this id in cache, but not all the subfields requested. so it immediately kicks back what it has:
{
data: {
map: {
id: 123,
name: "Map Name"
}
},
status: "loading"
}
then it fires off a server request:
{
query: {
map(id: $map_id) {
categories {
id
name
}
}
},
variables: {
map_id: "123"
}
}
after getting the remaining subfields, it combines with existing cache and redux so the stateToComputed receives the full result.
Option 2 something similar with more intervention by the user
Maybe this would expose the cache in a query callback or middleware that the user can return somehow, e.g.
cashay.query(mapDetailQuery, {
variables: { map_id },
fromCache: (cashayCache) => {
let cachedMap = cashayCache.find('Map', map_id);
if (cachedMap) {
return { name: cachedMap.name };
}
}
}
and maybe allow the eventual server response to override everything.
Closing in favor of preFetch RFC
Extending #153
If i have an items index route and items detail route. And I don't know how the user will enter.
This is how I'm attempting to use cache when possible:
Index component:
Detail component
This works.
It uses the cache when the user has already seen the index route. It makes a server request regardless, but the cached data is already rendered.
If the user enters the detail route directly, the server request resolves as normal which fills out the cache and, again, the cache is used to render.
But it feels clunky. Am I missing something?