- Published on
Handling API Errors Gracefully in React Query
- Authors
- Name
- Shelton Ma
APIError
1. Define a Custom Create a custom error class to encapsulate additional information about API errors, such as the response object:
// src/lib/errors.ts
export class APIError extends Error {
response: Response;
constructor(message: string, response: Response) {
super(message);
this.response = response;
}
}
2. Use APIError in React Query
Integrate the APIError class in your useMutation or useQuery hooks for better error handling.
// src/features/conversation/api/use-send-message.tsx
import { APIError } from "@/lib/errors";
import { client } from "@/lib/hono";
import { useMutation } from "@tanstack/react-query";
import { toast } from "sonner";
export const useSendMessage = () => {
const mutation = useMutation({
mutationFn: async (json) => {
const response = await client.api.conversation.$post({ json });
if (!response.ok) {
throw new APIError("Something went wrong", response);
}
return await response.json();
},
onError: (error: APIError | Error) => {
if (error instanceof APIError && error?.response.status === 403) {
toast.error("Free trial has expired");
}
toast.error("Failed to send message");
},
});
return mutation;
};
3. Handle Errors in Components
When using the custom hook in a component, handle errors gracefully in onError.
// src/app/(dashboard)/conversation/page.tsx
import { APIError } from "@/lib/errors";
const onSubmit = async (values: z.infer<typeof formSchema>) => {
mutate(
{ message: values["prompt"] },
{
onSuccess: (data: sendMessageResponseType) => {
setMessages(data.messages);
form.reset();
router.refresh();
},
onError: (error: Error | APIError) => {
if (error instanceof APIError && error?.response.status === 403) {
// Open ProModal
open();
}
},
}
);
};
By combining React Query’s powerful error handling capabilities with a custom error class, you can streamline error management in your Next.js applications.