T
TanStack16mo ago
adverse-sapphire

Custom hook to extract data property from axios response

Hi everyone! Is possible to create a custom vue query hook to return only the data attribute from AxiosResponse or only the content error from AxiosError (error.response.data)? I've tried to create a custom hook like this, but looks a wrong way to do that and the result has'nt been good I'm a begginer at vue.
import { DefaultError, QueryClient, QueryKey, UseQueryDefinedReturnType, UseQueryOptions, UseQueryReturnType, useQuery } from "@tanstack/vue-query";
import { AxiosResponse } from "axios";
import { isRef } from "vue";

type TOptions<
TQueryFnData,
TError,
TData,
TQueryKey extends QueryKey = QueryKey
> = UseQueryOptions<
AxiosResponse<TQueryFnData>,
TError,
TData,
AxiosResponse<TQueryFnData>,
TQueryKey
>

export function useAxiosQuery<
TQueryFnData = unknown,
TData = TQueryFnData,
TError = DefaultError,
TQueryKey extends QueryKey = QueryKey,
>(
options: TOptions<
TQueryFnData,
TError,
TData,
TQueryKey
>,
queryClient?: QueryClient
): (UseQueryDefinedReturnType<TData, TError> | UseQueryReturnType<TData, TError>) {
const newOptions = isRef(options) ? options.value : options;

const response = useQuery<
AxiosResponse<TQueryFnData>,
TError,
TData,
TQueryKey
>({
...newOptions,
select: (response) => {
if ("select" in newOptions && typeof newOptions.select === "function") {
// @ts-ignore
return newOptions.select(response.data);
}

response.data;
}
}, queryClient);

return response;
}
import { DefaultError, QueryClient, QueryKey, UseQueryDefinedReturnType, UseQueryOptions, UseQueryReturnType, useQuery } from "@tanstack/vue-query";
import { AxiosResponse } from "axios";
import { isRef } from "vue";

type TOptions<
TQueryFnData,
TError,
TData,
TQueryKey extends QueryKey = QueryKey
> = UseQueryOptions<
AxiosResponse<TQueryFnData>,
TError,
TData,
AxiosResponse<TQueryFnData>,
TQueryKey
>

export function useAxiosQuery<
TQueryFnData = unknown,
TData = TQueryFnData,
TError = DefaultError,
TQueryKey extends QueryKey = QueryKey,
>(
options: TOptions<
TQueryFnData,
TError,
TData,
TQueryKey
>,
queryClient?: QueryClient
): (UseQueryDefinedReturnType<TData, TError> | UseQueryReturnType<TData, TError>) {
const newOptions = isRef(options) ? options.value : options;

const response = useQuery<
AxiosResponse<TQueryFnData>,
TError,
TData,
TQueryKey
>({
...newOptions,
select: (response) => {
if ("select" in newOptions && typeof newOptions.select === "function") {
// @ts-ignore
return newOptions.select(response.data);
}

response.data;
}
}, queryClient);

return response;
}
2 Replies
xenial-black
xenial-black16mo ago
You're way overcomplicating this. Just return response.data from your queryFn directly. You don't need this very obscure wrapper composable on top of useQuery, as you won't be able to keep up with all the typing issues. You're going to lose most of automatic type inference. You're already adding ts-ignore. Also axios will throw by default for 4xx and 5xx requests. And that's what you generally want. If your backend returns 200 for generic error responses then you can generalize this with implementing response interceptor in axios.
adverse-sapphire
adverse-sapphireOP15mo ago
I partially agree with your arguments; however, my application has a large number of API calls, and parsing the response in each place that uses Vue Query is impractical, repetitive, error-prone, and generates a lot of boilerplate. A hook of this type is not obscure; it centralizes the work of parsing responses in a single place. If I use Axios interceptors, I will have to override the response and error types. If one day I want to switch the application's HTTP Client, I know I can replace the type of this hook with that of the new Client, and TypeScript would already flag errors in all the places where I need to make changes. I started this discussion because I am a beginner in TypeScript and understand that using ts-ignore is not ideal and can cause problems in the long run. However, this idea for such a hook is plausible and would greatly help in the development of applications with numerous calls.

Did you find this page helpful?