npm i hono-query
import { q } from "hono-query";
export const MyReactComponent = () => {
const { data: userData1 } = useQuery(q(() => api.auth.current_user.$get()));
// queryOptions are generated automatically with
// { queryKey: ["auth.current_user.$get()"], queryFn: ... }
// where queryFn simply returns the json data from the endpoint.
// return types are inferred.
const { data: userData2 } = useQuery(
q(() => api.auth.current_user.$get(), {
queryKeyComplement: ["some extra key", userId],
})
);
// you can call q with the RPC endpoint and also an option object:
// optionally pass an array of keys to add to the key:
// queryKey: ["auth.current_user.$get()", "some extra key", "someUserIdValue"]
const { data: userData3 } = useQuery(
q(() => api.auth.current_user.$get(), {
queryKeyComplement: ["some extra key", userId],
retry: 5,
staleTime: 5 * 1000,
})
);
// you can call q with the RPC endpoint and also an option object with
// an optional queryKeyComplement and any regular queryOption property
};
The "problem" now is that we need to write queryKeys and queryFunctions for all routes, as is done here. It seems cumbersome and redundant to add React Query helper functions for all routes when they are all available on the Hono client.
According to this comment this is missing to a few people and a selling point for tRPC over Hono RPC.
I tried to generate Tanstack queryKey, queryFn and queryOptions by reusing as much of the autocompletion that Hono client provides.
In your frontend code you can do the following:
import { q } from "hono-query";
queryClient.fetchQuery(
q(
() => api.dashboard.deployments.user[":userId"].$get({ param: { userId } }), // the RPC endpoint you're targeting
{
queryKeyComplement: [userId], // a complement you might want to add to the queryKey
// all properties other than queryKeyComplement are regular queryOptions
retry: 5, // optionally pass any additional query options
retryDelay: 1000, // optionally pass any additional query options
staleTime: 5 * 1000, // optionally pass any additional query options}
}
)
);
and this will seamlessly generate the query key and function pair that you need when using React Query:
{
queryKey: [
"dashboard.deployments.user[\":userId\"].$get({ param: { userId } })", // The endpoint is turned into a function name using toString(), which is sometimes replacing variables by name, sometimes by value, I'm not sure exactly why or how
"6h8s62e7uppe4ee" // The queryKeyComplement. This is dynamic (variables are passed by value, userId has been replaced by "6h8s62e7uppe4ee")
],
queryFn: async () => {
const res = await api.dashboard.deployments.user[":userId"].$get({ param: { userId } });
return (await res.json()) as InferResponseType<T>;
},
retry: 5, // optionally pass any additional query options
retryDelay: 1000, // optionally pass any additional query options
staleTime: 5 * 1000, // optionally pass any additional query options}
}
- Only works for endpoints that return json
- Type errors with useSuspenseQuery
Your contributions are welcome.