Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the type of React Query's Error and how to handle different cases?

I'm using React Query with typescript to fetch data in my project and I'm trying to use the error the useQuery hook returns to display a message describing the error if it exists like this :

{isError && (error)? <p className=" text-[#ff0000] text-center font-semibold">{error?.response.data.message}</p> : null}

I'm having a problem with the error type : enter image description here

How can I fix it, I couldn't find anything on the internet and if possible can anyone explain how to handle different thrown error with react query since you can throw anything in JS/TS

like image 919
Hazem Ben Abdelhafidh Avatar asked Sep 05 '25 03:09

Hazem Ben Abdelhafidh


2 Answers

error defaults to type unknown because your queryFn can throw anything, that's a javascript behaviour. throw 5 will give you number as your error type. There is no good way to assert that, so unknown is the best possible type. It's also what TypeScript does now per default since v4.4 (useUnknownInCatchVariables)

The best way to make sure that your app runs as you want is to narrow the type at runtime. if (error instanceof Error) does the trick, and the you can safely access error.message.

If you are using axios, the type is actually an AxiosError, and axios has an axios.isAxiosError(error) helper that checks for that and also narrows the type correctly.

The alternative is to provide generics to useQuery:

useQuery<Todo[], AxiosError>(['todos'], fetchTodos)

but this is bad for a couple of reasons:

  1. there are actually four generics, and you remove a bunch of features by only providing two of them
  2. There is no guarantee that your error will really be an axios error. For example, if you use select, and a runtime error happens in there (because of some faulty logic), your error will be a "normal" Error, but not an axios Error.

Alas, as you can throw anything in JS, unknown is the most correct type.

I'm also going into more details in my blog:

https://tkdodo.eu/blog/react-query-and-type-script

Update: Since v4 "the type for error defaults to Error". Read more in the docs.

like image 68
TkDodo Avatar answered Sep 07 '25 20:09

TkDodo


As @TkDodo has pointed out, you could provide generics to useQuery but it's not worth it, since you will lose the Type inference too.

However, as a workaround, I add the onError callback and type its error arg instead. TypeScript will infer the type of that error to the type I am expecting from useQuery.

Note that I am using Axios request & response interceptors for all requests that I use to format and throw my custom errors.


Example...


interface IPayload {
  someKey: string; // ETC
}

// The type of error expected from the response (also formatted by interceptor).
interface IApiError {
  message: string;
  description: string;
  statusCode: string | number;
}

export const useMyQuery = (payload: IPayload) => {
  const { data, isLoading, isError, error, refetch } = useQuery({
    queryKey: ['some', 'query-keys'],
    queryFn: () => API.fetchMyData(payload),
    // This does the trick
    onError: (err: IApiError) => err,
  });
};
like image 20
iamcastelli Avatar answered Sep 07 '25 21:09

iamcastelli