Skip to content

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

Merged
merged 3 commits into from
May 14, 2025

Conversation

ryan953
Copy link
Member

@ryan953 ryan953 commented May 13, 2025

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

@ryan953 ryan953 requested a review from a team as a code owner May 13, 2025 22:24
@ryan953 ryan953 changed the base branch from ryan953/fix-feedback-mark-as-read to master May 13, 2025 22:25
@github-actions github-actions bot added the Scope: Frontend Automatically applied to PRs that change frontend components label May 13, 2025
@ryan953 ryan953 requested review from a team and billyvg May 13, 2025 22:27
@@ -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]);
Copy link
Member Author

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]
Copy link
Member Author

@ryan953 ryan953 May 13, 2025

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.

https://tkdodo.eu/blog/effective-react-query-keys#structure

Comment on lines -250 to -257
// 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),
Copy link
Member Author

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.

@ryan953 ryan953 merged commit 8101250 into master May 14, 2025
42 checks passed
@ryan953 ryan953 deleted the ryan953/fix-InfiniteApiQueryKey branch May 14, 2025 17:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Scope: Frontend Automatically applied to PRs that change frontend components
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants