T
TanStack7mo ago
conscious-sapphire

Multiple query keys loading the same data [ANSWERED]

Suppose I have the following screens: * All posts (GET /posts) * User's posts (GET /users/{userId}/posts) * Post details (GET /posts/{postId}) When accessing the post details, I want the initialData to check if this post was previously loaded by either the all posts query, or the user's posts query. I did this in the initial data by checking both separately using queryClient.getQueryData as such:
const {
data: post,
isLoading,
isError,
refetch,
} = useQuery({
queryKey: ['posts', postId],
queryFn: () => PostsAPI.getById(postId),
initialData: () => {
// Check if the post was fetched by userPosts
const userPosts = queryClient.getQueryData<Post[]>(
['userPosts', userId]
);
const post = userPosts?.find((p) => p.id === postId);

if (post) return post;

// Check if the post was fetched by all posts
const allPosts = queryClient.getQueryData<Post[]>(
['posts']
);
const post = allPosts?.find((p) => p.id === postId);

if (post) return post;
},
});
const {
data: post,
isLoading,
isError,
refetch,
} = useQuery({
queryKey: ['posts', postId],
queryFn: () => PostsAPI.getById(postId),
initialData: () => {
// Check if the post was fetched by userPosts
const userPosts = queryClient.getQueryData<Post[]>(
['userPosts', userId]
);
const post = userPosts?.find((p) => p.id === postId);

if (post) return post;

// Check if the post was fetched by all posts
const allPosts = queryClient.getQueryData<Post[]>(
['posts']
);
const post = allPosts?.find((p) => p.id === postId);

if (post) return post;
},
});
At a first glance this does not look correct because it's violating DRY. But what is the proper way? The solution that comes to mind is to pass the post as a prop to the post details and have that as the initial data, and meanwhile make a query to posts/{id}, but I'm not 100% sure of this approach
5 Replies
conscious-sapphire
conscious-sapphireOP7mo ago
I have found a satisfactory answer for those who are facing a similar issue. The approach is to have the screen that will navigate to the postDetails set the queryData before doing so, like so:
queryClient.setQueryData(['posts', postId], post);
queryClient.setQueryData(['posts', postId], post);
Then removing the initialData entirely.
conscious-sapphire
conscious-sapphire7mo ago
Hi there, there are a couple of methods for prefilling the cache. You can prefetch a query, or if you already have data from another query, you can push/pull this data into the cache.
conscious-sapphire
conscious-sapphire7mo ago
Seeding the Query Cache
With suspense for data fetching on the horizon, it is now more important than ever to make sure your cache is seeded properly to avoid fetch waterfalls.
conscious-sapphire
conscious-sapphire7mo ago
Read this article on both methods, their pros/cons
conscious-sapphire
conscious-sapphireOP7mo ago
Thank you! That’s exactly what I was looking for

Did you find this page helpful?