-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
Describe the feature you'd like to request
I have query procedure listPosts which accepts some generic parameters and and optional lastUpdatedAt timestamp.
The query key looks something like this:
[["posts","list"],{"input":{ "parameters": {} },"type":"query"}]
This query is expensive, so I cache it also on the server with the given parameters as caching key in case multiple clients request the same data. When I receive the same parameters on the server, I return the data from the cache.
Now I need some way for clients to force a refresh on the server returning new data instead of cached data for the same parameters. So in this case, I query the listPosts with an optional lastUpdatedAt timestamp. The query key is now:
[["posts","list"],{"input":{ "parameters": {}, "lastUpdatedAt": 123456789 },"type":"query"}]
The servers receives the same parameters as before and finds the data in the cache, but the lastUpdatedAt timestamp is greater than the cached timestamp. So it runs the expensive operation on the server and returns the new data (and caches it).
Now I have two query keys on the client which are logically the same. I must update the query data of key 1 and key 2 with new data, because query key 2 is only temporary to trigger a server cache-invalidation. The lastUpdatedAt that I sent in query key 2 is a local state that will get lost after page navigation. When I later get back to the ListPosts page, it will use query key 1 again with data which was maybe set by query key 2.
I'm currently using onSuccess of useQuery to set the query data of all query keys matching the input without lastUpdatedAt:
type Input = {
parameters: Record<string, any>;
lastUpdatedAt?: number;
};
const query = trpc.posts.list.useQuery(input, {
onSuccess(data) {
const { lastUpdatedAt, ...restInput } = input;
// update the query cache for all entries with the same parameters, but ignoring the lastUpdatedAt date
queryClient.setQueriesData(getQueryKey(trpc.posts.list, restInput), data);
},
});That means it sets the data for query key 1 (without lastUpdatedAt) and 2 (with lastUpdatedAt).
However, onSuccess was deprecated in React Query v5, so I'm looking for an alternative option.
Allowing to overwrite the generated tRPC query key would make it possible to send different inputs to the server but with the same query key.
Describe the solution you'd like to see
I would like to overwrite the query key via the tRPC query options:
const query = trpc.posts.list.useQuery(input, {
trpc: {
// static query key overwrite
queryKey: [["posts","list"],{"input":{ "parameters": {} },"type":"query"}],
// OR
// dynamic query key overwrite
queryKey: () => {
// remove field that should not be passed to server
const { lastUpdatedAt, ...restInput } = input;
return getQueryKey(trpc.posts.list, restInput)
},
},
});That means the following two inputs produce the same query key:
// = query key: [["posts","list"],{"input":{ "parameters": {} },"type":"query"}]
const input1 = {
parameters: {},
}
// = query key: [["posts","list"],{"input":{ "parameters": {} },"type":"query"}]
const input2 = {
parameters: {},
lastUpdatedAt: 123456789
}By default, React Query would return the data from the query cache for both inputs. So we would need to use the refetch() function to manually trigger a refetch to the server with new input.
Describe alternate solutions
useQuery.onSuccess()was deprecated in v5, but could be implemented again with auseEffect()with dependency touseQuery.data
const { data } = trpc.posts.list.useQuery(input);
// update all queries every time the data changes
React.useEffect(() => {
const { lastUpdatedAt, ...restInput } = input;
queryClient.setQueriesData(getQueryKey(trpc.posts.list, restInput), data);
}, [data, queryClient, input]);- use
useQuerydirectly with the proxy client and change the query key
const { lastUpdatedAt, ...restInput } = input;
const queryKey = getQueryKey(trpc.posts.list, restInput);
const query = useQuery({
queryKey,
queryFn: (context) => {
return utils.client.posts.list.query(input)
},
});Additional information
No response
👨👧👦 Contributing
- 🙋♂️ Yes, I'd be down to file a PR implementing this feature!