TanStackT
TanStack3y ago
1 reply
exclusive-coral

Triggering refetch without changing query keys

Not sure if title is relevant, but here is my case based on simplified example:

I'm creating mobile music player app. User can browse and search different songs within the app. Those songs are fetched from external service (using react query ofc).
User can also like a song - if he does it, song id is added to "favorites" array stored and saved on the device. That way we can check if particular song id exists in this array and highlight if song is liked on the UI.
But user can also go to dedicated screen, where he can list all his liked songs. As we only have songs ids, we need to do a fetch to external service, which returns us full songs data based on provided ids.

And here is a case - how to construct query for that?
Currently I'm just passing whole song ids array to query key:
const likedSongIds = useLikedSongIds();
const query = useQuery({
  queryKey: ['likedSongs', ...likedSongIds],
  queryFn: () => fetchSongsByIds(likedSongIds)
})

It works, but there are 2 main issues with that:
1. Any time track is added to liked songs, and we navigate to liked songs screen, it will end up in hard loading state and show basically nothing on the UI, despite the fact that we have data of all songs except the new one in this query data. What I would like to achieve in that case, is to show previous state (all tracks besides the new one) and maybe add some small loading indicator. Sounds like a case for keepPreviousData, but it only works if the screen remains mounted.
2. Garbage collection. In my case, I only care about results for current set of likedSongIds and when query key changes, I would like to immediately remove data from previous key from cache. Setting cacheTime: 0 doesn't really work because I'm persisting cache to device storage. So, as far as I understand, when the app is killed and opened again, data for likedSongs will be removed because it's not mounted on initial screen.
Was this page helpful?