Using the result pattern with react query #10660
Replies: 1 comment
-
|
The trick is not to fight react-query's error model — adopt it. React Query is built around the convention that The cleanest pattern is to keep using your const myQueryFn = async (): Promise<User> => {
const result = await getUserAction();
if (result.error) throw result.error; // AppError<...> is what gets thrown
return result.data;
};
const { data, error } = useQuery({
queryKey: ["user"],
queryFn: myQueryFn,
});
// `error` is typed as AppError<...> if you keep the throw site typed.
// Narrow on error.type to render the right UI.To preserve full type inference for useQuery<User, AppError<"NOT_FOUND" | "FORBIDDEN" | "UNKNOWN_ERROR">>({
queryKey: ["user"],
queryFn: myQueryFn,
});You still get autocomplete on For mutations the same idea works — throw inside |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hello everyone,
I really like the result pattern and the principle of never throwing to not loose an error that occured in nested try-catches for example. It really helped me to show the specific error that occured to the user and not just a generic message like "Something went wrong". I'm also using next.js server actions. This makes it possible to have full autocomplete for query.data.error.type for example. This way i can tread each error differently on client side.
export type AppError<C extends string> = { type: C | 'UNKNOWN_ERROR' title: string description: string }export type Success<T> = { data: T; error: null }export type Failure<E> = { data: null; error: E }export type Result<T, E extends AppError<string> = AppError<string>> = | Success<T> | Failure<E>However the issue I'm having using react query is that not throwing in the query function deveats the whole purpose of isError and isSuccess because it will always be treated as a successful data fetch.
I already thought about a callback function unpacking the result pattern and throwing the error result on error after fetching. But now i don't have the autocompletion and type safety of query.data.error.type anymore because the error thrown is unknown. I could use generics for defining the error type but if i understood it correctly @TkDodo does not recommend using generics because of some type inference issues.
Does anyone have a solution so i can deal with specific errors differently in react components but also have react query behave correctly and tell isError and isSuccess correctly?
Also i really don't want to miss out on the autocompletion of my current way of doing it, because with this i always know which exact errors are thrown by a server action.
Beta Was this translation helpful? Give feedback.
All reactions