Comments (13)
Hey @danielkaxis, thanks for opening this issue. I'll have to check into this as well because I just ran across this same problem when using React.lazy
– useQuery
underneath it doesn't seem to keep the Suspense boundary in a loading state 🤔
from urql.
I have been trying to make this work as good as I can but ultimately this is not really a structure we want to encourage, you can ofcourse make it work with an exchange that does the deduping for you.
The pattern here is a bit counter to GraphQL where you are creating a lot of requests throughout your application that are inter-dependent rather than one big selection-set.
Alright, thanks @JoviDeCroock. I'm beginning to understand the issue. My ideas were pointing at that direction when I wrote the previous message. We do have several queries accessing the same entities like in my example. @HitomiWin tried the deduping you linked and said it seems to work.
The better way is to do one query. We will try this out. Thank you so very much!
from urql.
Hey,
It's really unclear what you are expecting to happen here or how we would observe the issue. I would encourage you to give us clear reproduction/observation steps and upgrade your urql dependencies.
The logger API can also provide insight into what's happening https://commerce.nearform.com/open-source/urql/docs/api/graphcache/#cacheexchange
from urql.
Hey @JoviDeCroock,
Thanks for your reply. I have now updated the example and intructions.
Thanks for the tip about the logger API. I will check that out.
from urql.
Hey,
I have tried to console log the issues with the logger function.
It looks that queries once called are not cached ??? 🤔
from urql.
As I've said before, it's quite hard to deduct what's going on in your reproduction. I'll try to spend some time on this over the next week, something that could go a long way would be for you to check whether it helps to
- Hoist client creation to the global scope (as it stands you do
initClient
in aSuspense
tree without memo/... which is dangerous in and of itself) - Identify at what version this started happening
from urql.
As I've said before, it's quite hard to deduct what's going on in your reproduction. I'll try to spend some time on this over the next week, something that could go a long way would be for you to check whether it helps to
- Hoist client creation to the global scope (as it stands you do
initClient
in aSuspense
tree without memo/... which is dangerous in and of itself)- Identify at what version this started happening
Sorry if my new example is also unclear. I really really tried 😿 I'm not sure how I can explain it better. Thanks for the tip. I will try it.
from urql.
It is def weird that it's being re-queried, it almost feels like GraphCache is just removing data. This might just come down to layers and the mutation layer skewing here 😅 mainly because all operations are in-flight at the same time.
Currently don't have time to debug this but ye, might be something in there. Your thesis is correct though that this produces multiple requests, when using the debugExchange
I can clearly see that every request is duplicated.
Update after spending the evening on this, the offending lines are situated here. Basically we should change this up to check whether it's not queued and whether the dispatched does not contain it yet like:
if (!queued && (!dispatched.has(operation.key) || operation.context.requestPolicy === 'network-only')) {
queue.push(operation);
Promise.resolve().then(dispatchOperation);
} else {
dispatched.delete(operation.key);
Promise.resolve().then(dispatchOperation);
}
That however re-introduces the issue we faced in #3254 where we do an optimistic mutation which results in the dispatch
and when the response comes in the updater results in a second dispatch
this second one does not go throug has the optimistic reexecute is seen as dispatched
. Will need some more time on this but thought I'd update this issue already 😅
from urql.
It is def weird that it's being re-queried, it almost feels like GraphCache is just removing data. This might just come down to layers and the mutation layer skewing here 😅 mainly because all operations are in-flight at the same time.
Currently don't have time to debug this but ye, might be something in there. Your thesis is correct though that this produces multiple requests, when using the
debugExchange
I can clearly see that every request is duplicated.Update after spending the evening on this, the offending lines are situated here. Basically we should change this up to check whether it's not queued and whether the dispatched does not contain it yet like:
if (!queued && (!dispatched.has(operation.key) || operation.context.requestPolicy === 'network-only')) { queue.push(operation); Promise.resolve().then(dispatchOperation); } else { dispatched.delete(operation.key); Promise.resolve().then(dispatchOperation); }That however re-introduces the issue we faced in #3254 where we do an optimistic mutation which results in the
dispatch
and when the response comes in the updater results in a seconddispatch
this second one does not go throug has the optimistic reexecute is seen asdispatched
. Will need some more time on this but thought I'd update this issue already 😅
Wow! This is amazing news. I can try to test this locally and see if the issue goes away :)
On a side note, hoisting of urql did not help.
from urql.
Thanks @JoviDeCroock! We will upgrade our packages and make sure it works. Much appreciated.
from urql.
Sadly, these changes did not make it for us. I have an updated example project with the upgraded packages.
"@graphql-tools/schema": "10.0.3",
"@urql/core": "5.0.2",
"@urql/devtools": "2.0.3",
"@urql/exchange-execute": "2.2.2",
"@urql/exchange-graphcache": "7.0.2",
"graphql": "16.8.1",
"urql": "4.0.7",
createClient is now used from @urql/core
The updated example can be seen here. I have trimmed down the example even more to remove bloat code that is confusing. I have also added a query to an entity that exists directly under Query. The schema now looks like this in graphql.ts.
Query
- User
- Vehicle
Vehicle
- cars
- car(id)
Car
- id
- name
Compared to the example in the issue description Car:name
is now called 10 times instead of 8 so there was a change with the update.
I will start from scratch. I have 4 cars.
In Vehicles.tsx I have a query to fetch cars
under Vehicles
under Query
. That query contains the id
and name
and that data should now be cached
.
For every car I return a new component Car. In Car I have a query to fetch car
with a specified id
. That query should in theory give me the cached data. However it doesn't. It calls the resolver again.
This image shows only cars query
in Vechicles.tsx. is removed and not querying any data. Car:name
is called 4 times. That is good and what I expect.
This image shows together with car querying data for a specific id. For every car
id I query Query:Vechicle:car(id)
. I expect that query to give me cached data. But it doesn't. It calls the resolver again. Car:name
is now called 10 times.
As in the initial example I also remove the mutation before the lazy loading is complete. Car:name
is now only called 8 times.
Interesting as well is that I also added a user query
in Car.tsx but that query is returning cached data and only calls User query: 1 which is good and what is expected.
To be honest I don't think this is even related to anymore. When I remove Suspense and just render the components normally I get the same behaviour.
On a side note:
In our real project we managed to workaround the issue of duplicate requests. We did that by using createClient from @urql/core instead of urql and downgrading @urql/core from 4.2.0
to 4.1.1
. This did not work in my example though.
from urql.
I have been trying to make this work as good as I can but ultimately this is not really a structure we want to encourage, you can ofcourse make it work with an exchange that does the deduping for you.
The pattern here is a bit counter to GraphQL where you are creating a lot of requests throughout your application that are inter-dependent rather than one big selection-set.
from urql.
I want to post an updated example project for anyone interested in the outcome of this issue.
https://github.com/danielkaxis/urqlsuspensetest/tree/multiplerequestsresolution
I removed the additional query document for fetching a single car. I now only have one document fetching all cars.
The schema is still as before.
// Schema
Query
vehicle
Vehicle
car
cars
Car
name
// Query
export const VehiclesDocument = gql`
query {
vehicle {
cars {
id
name
}
}
}
`
To demonstrate:
In Vehicles.tsx I query VehiclesDocument.
https://github.com/danielkaxis/urqlsuspensetest/blob/multiplerequestsresolution/src/components/Vehicles.tsx
In Car.tsx I also query VehiclesDocument
https://github.com/danielkaxis/urqlsuspensetest/blob/multiplerequestsresolution/src/components/Car.tsx
I have 4 cars
I also see them called only 4 times 😄
from urql.
Related Issues (20)
- Possible memory leak when using multiple queries on the same page HOT 7
- requestPolicyExchange does not re-request in production HOT 3
- cacheExchange - cache.readQuery (updateQuery) can't find queries with aliased variables HOT 1
- @urql/exchange-persisted Module name, 'crypto' does not resolve to a valid URL. HOT 7
- Non RSC authExchange failing HOT 2
- Problem: @urql/exchange-graphcache updateCacheWithResult reads null after writing link in cache updater. HOT 8
- Invalidating cache in Graphcache doesn't trigger query refetch in Next.js app router HOT 2
- RFC: react native file upload support HOT 1
- Introspected schema from urql-introspection doesn't match type of exchange-graphcache HOT 1
- RFC: Graphcache strong typing HOT 3
- Graphcache: mutations with different files in parallel, results lost HOT 3
- Invalidate with a key does not produce expected result HOT 2
- RFC: Normalize embedded documents based on parent HOT 5
- Syntax Error: Unexpected token in SelectionSet HOT 1
- RFC: @urql/vue - Allow getter syntax in `useQuery` HOT 4
- RFC: Add secondary keys HOT 2
- @urql/exchange-graphcache returns empty data & error although fetch response contains valid data. (when same entity is requested in parallel) HOT 1
- ExecuteExchange doesn't interact well with "server-only" code HOT 1
- (vue) useQuery pause does not update when passing a ref HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from urql.