-
-
Notifications
You must be signed in to change notification settings - Fork 3k
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
fix: no hydration when new promise comes in #8383
base: main
Are you sure you want to change the base?
fix: no hydration when new promise comes in #8383
Conversation
View your CI Pipeline Execution ↗ for commit 3c1b221.
☁️ Nx Cloud last updated this comment at |
before digging deeper, can you confirm if this is a bug or expected @TkDodo ? I think we might not be in a pending state so the promise doesn't get sent down? |
// --- server --- | ||
countRef.current++ | ||
const promise2 = serverQueryClient.prefetchQuery(query) | ||
|
||
const dehydrated2 = dehydrate(serverQueryClient) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assume this is a server fn calling revalidatePath()
so the page re-renders
you’re right: we only send the promise when we are in |
feels like we need some other state that would let us know if the promise is fresher then we need to set the queries' promise or something.. this goes deeper than I thought |
I'd say if we get a promise, we should always assume it's newer and hydrate its data, no? |
how do we check for that wihtout causing infinite re-renders in |
struggling to figuring out how to properly filter out the queries to put in the hydration queue CleanShot.2024-12-02.at.21.01.26.mp4 |
@juliusmarminge have you widened this check? query/packages/react-query/src/HydrationBoundary.tsx Lines 74 to 76 in 8fe9010
to something like:
so that whenever a promise is included, we put it the queue. |
yea that causes infinite rerenders |
interesting; let’s debug that together today if you have some time? |
sure! what time? I can sneak in a short seesion anytime after 10am gmt+1. |
I pinged you on discord ;) |
existingQuery.state.dataUpdatedAt | ||
existingQuery.state.dataUpdatedAt || | ||
// @ts-expect-error | ||
dehydratedQuery.promise?.status !== existingQuery.promise?.status |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this might actually be working
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if we prefetch a query without await
in a page that is static or cached, either fully or partially, and then client navigate to it with newer data in the cache? My guess is that there are/can be situations where we get a promise that will resolve to data that is actually older than the one we have on the client already?
Maybe the entirely correct way to do this would be to inspect the data the query resolves to before determining whether to update the cache with that data? Implementation-wise that's a lot tricker though unfortunately. :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the entirely correct way to do this would be to inspect the data the query resolves to
this is something only users could verify though. Without query meta-data like dataUpdatedAt
, react-query doesn’t know the age of the data. Are you suggesting we provide a way for users to extract a timestamp (age) from the promise data in some sort of callback option?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it? If we are using the fetch timestamp from the server to determine this when hydrating data, we can surely do that for promises too, just after they resolved? I'm sure it might be a big painful thing to implement, but is there some inherent thing about user/library land that blocks us from doing this in the library using the same logic?
To be clear, if we already have this query in the cache, this might require us to wait for the promise outside of the cache and only put the data in. Or even worse, to support fetching states properly, it might requires us to have some sort of "possibleUpdatePromise" or something that would not commit it's result to the cache if it's older.
@juliusmarminge what are we gonna do with this one? |
Sorry completely forgot about this 😅 I think I had it sort of working but happy to jump on a call and talk about it still! Hit me up on discord when you have some time to go over it! |
otherwise, we risk including promises that happen because of background updates (think persistQueryClient)
otherwise, we are re-using the cache and the query won't be in "pending" state the second time around
No description provided.