Open nickzelei opened 1 month ago
Thanks for the issue! In general, invalidating queries (triggering a refresh) instead of manipulating the cache is preferable because it's so simple and reliable (for example, you'll never forget to also update a lastUpdated
property).
For example, I've often seen a pattern like this:
const res = useMutation(createMyValue, {
onSuccess: (data) =>
queryClient.invalidateQueries({
queryKey: createConnectQueryKey(geyMyValue, {
id: data.id,
}),
})
});
I'm not closely familiar with swr. Is it more common to update the cache than to let it update?
Thanks for the response! Unclear if it's more common or not to do that. swr
works effectively the same way as the refetch
does with their mutate
, but they optionally allow you to provide a cache value.
Since our mutation APIs like Create, Update return the latest object, I like to optimistically update the cache because we have the latest object instead of just calling refetch again to hit the API one more time.
Perhaps this is an anti-patten and it's just way more common to simply call refetch or invalidate.
Since our mutation APIs like Create, Update return the latest object, I like to optimistically update the cache
I'm not sure I'd call it an anti-pattern, just that I would generally recommend to invalidate and refetch for simplicity. Makes perfect sense to me to not waste a roundtrip, if you know what you're doing 🙂
Here's the tanstack/query guide on this topic: https://tanstack.com/query/latest/docs/framework/react/guides/updates-from-mutation-responses
Maybe the most straight-forward improvement would be a function similar to this:
import {type Message, type PartialMessage,} from "@bufbuild/protobuf";
import {QueryClient} from "@tanstack/react-query";
import {createConnectQueryKey, type MethodUnaryDescriptor} from "@connectrpc/connect-query";
export function setQueryData<
I extends Message<I>,
O extends Message<O>,
>(
client: QueryClient,
methodDescriptor: Pick<MethodUnaryDescriptor<I, O>, "I" | "name" | "service">,
input: PartialMessage<I>,
output: O,
): void {
const key = createConnectQueryKey<I, O>(methodDescriptor, input);
client.setQueryData(key, output);
}
It just provides a bit of type-safety for RPCs on top of QueryClient.setQueryData
. Maybe we can add it to the package if it works out well.
Although I think we could make it a little easier with a custom QueryClient, we do have a helper method to handle these kinds of things: createProtobufSafeUpdater
.
We've been internally playing with the idea of exporting a custom QueryClient that provides common helper methods for interacting with the query client in a typesafe way but that will probably wait till everything has been moved over to protobuf-es@v2 anyways.
Hey all, awesome project! This is allowing me to easily switch away from
swr
over to usingtanstack/query
.One thing I miss however is the ability to easily update the query cache.
With swr, each instance has a
mutate
function that includes the curried key, so I can easily pass it the new value. With the current iteration of this library, therefetch
function that is returned fromuseQuery
takes no parameters.In order for me to update the underlying cache, I have to do something like this:
I'd love it if there were an easier way to trigger a cache update for a
useQuery
value that didn't involve so much boilerplate.