-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
fix(queryClient): useInfiniteApiQuery should require unique queryKeys, not create them #91601
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
Conversation
@@ -52,7 +52,7 @@ export default function useFetchFeedbackData({feedbackId}: Props) { | |||
if (issueResult.isFetched && issueData && !issueData.hasSeen) { | |||
markAsRead(true); | |||
} | |||
}, [issueResult.isFetched]); // eslint-disable-line react-hooks/exhaustive-deps | |||
}, [issueData, issueResult.isFetched, markAsRead]); |
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 seemed wrong before. Because we were just looking at isFetched i think if you toggled back and forth between two unread feedbacks (so both are in cache), then we wouldn't re-run the useEffect when the visible feedback changed. We want to re-run it in case something else has flipped the hasSeen bit and we want to reset it.
@@ -49,6 +49,17 @@ export type ApiQueryKey = | |||
Record<string, any> | |||
>, | |||
]; | |||
export type InfiniteApiQueryKey = | |||
| readonly ['infinite', url: string] |
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.
added this const as a prefix because: most generic to most specific is the best order.
// We append an additional string to the queryKey here to prevent a hard | ||
// crash due to a cache conflict between normal queries and "infinite" | ||
// queries. Read more | ||
// here: https://tkdodo.eu/blog/effective-react-query-keys#caching-data | ||
queryKey: | ||
queryKey.length === 1 | ||
? ([...queryKey, {}, 'infinite'] as const) | ||
: ([...queryKey, 'infinite'] as const), |
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.
Now you're required, per TS, to pass in a key that includes the string 'infinite'
at the start. ApiQueryKey
and InfiniteApiQueryKey
are not subclasses of each other, but it's possible to convert from one to the other.
What was previously happening since #86421 is that we would silently change the queryKey that was passed into
useInfiniteApiQuery
to have'infinite'
suffixed to the end. This was leaky if any code wanted to interact with the query cache it had to add the same suffix.Well, now the suffix is a prefix, and is required when you call
useInfiniteApiQuery()
. This will ensure that all queryKeys for useInfiniteApiQuery are unique (as we did before) but also will make sure that the same queryKey will work for fetching the data and interacting with the cache.Replaces #91596
Followup to #86421