typescript - Tanstack React Query useMutation întotdeauna True în onSuccess
import { TNewServicesProps } from '@/_constants/types';
import api from '@/_libs/api';
import { useMutation, useQueryClient } from '@tanstack/react-query';
const useManageServices = (
method: 'create' | 'update' | 'delete',
item_id?: number | string,
values?: TNewServicesProps
) => {
if ((method === 'update' || method === 'delete') && item_id == null) {
throw new Error(`item_id is required for ${method} method`);
}
const queryClient = useQueryClient();
const { data, error, isPending, mutateAsync, isSuccess } = useMutation({
mutationKey: [`${method}_services`],
mutationFn: async () => {
switch (method) {
case 'create':
return await api
.post(
`/admin/services/`,
JSON.stringify(values !== undefined ? values : {})
)
.then((res) => res.data)
.catch((error) => error.response.data);
case 'update':
return await api
.patch(
`/admin/services/${item_id}/`,
JSON.stringify(values !== undefined ? values : {})
)
.then((res) => res.data)
.catch((error) => error.response.data);
case 'delete':
return await api
.delete(`/admin/services/${item_id}/`)
.then((res) => res.data)
.catch((error) => error.response.data);
default:
throw new Error(`Invalid method: ${method}`);
}
},
//this is always fired, even when response code is 400, 500, etc.
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ['services'],
});
},
onError: () => {
//should do something but never fired
},
});
return { data, error, mutateStatus: mutateAsync, isPending, isSuccess };
};
export default useManageServices;
În prezent experimentez cu react-query în proiectul meu.
Mă confrunt cu o problemă legată de gestionarea erorilor în cadrul mutației mele.
Când verific fila rețelei, pot vedea că serverul răspunde fie cu un cod de stare 400, fie 500, ceea ce am presupus că ar determina axios să arunce o eroare, declanșând funcția onError definită.
Totuși, funcția onSuccess este întotdeauna apelată.
Ce aș putea să trec cu vederea? Mulțumesc anticipat.
Răspuns #1
Bănui că problema aici este că funcția ta de mutație prinde erorile aruncate înainte ca hook-ul useMutation să le poată gestiona pentru a invoca efectiv orice handler onError furnizat.
Suspectez că ai putea fie să nu le prinzi deloc, fie să le arunci din nou după ce au fost gestionate.
const { data, error, isPending, mutateAsync, isSuccess } = useMutation({
mutationKey: [`${method}_services`],
mutationFn: async () => {
switch (method) {
case 'create':
return await api
.post(
"/admin/services/",
JSON.stringify(values !== undefined ? values : {})
)
.then((res) => res.data);
case 'update':
return await api
.patch(
`/admin/services/${item_id}/`,
JSON.stringify(values !== undefined ? values : {})
)
.then((res) => res.data);
case 'delete':
return await api
.delete(`/admin/services/${item_id}/`)
.then((res) => res.data);
default:
throw new Error(`Invalid method: ${method}`);
}
},
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ['services'],
});
},
onError: () => {
// ...
},
});
const { data, error, isPending, mutateAsync, isSuccess } = useMutation({
mutationKey: [`${method}_services`],
mutationFn: async () => {
switch (method) {
case 'create':
return await api
.post(
"/admin/services/",
JSON.stringify(values !== undefined ? values : {})
)
.then((res) => res.data)
.catch((error) => {
// error.response.data
throw error;
});
case 'update':
return await api
.patch(
`/admin/services/${item_id}/`,
JSON.stringify(values !== undefined ? values : {})
)
.then((res) => res.data)
.catch((error) => {
// error.response.data
throw error;
});
case 'delete':
return await api
.delete(`/admin/services/${item_id}/`)
.then((res) => res.data)
.catch((error) => {
// error.response.data
throw error;
});
default:
throw new Error(`Invalid method: ${method}`);
}
},
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ['services'],
});
},
onError: () => {
// ...
},
});
Răspunsul #2
Așa cum a menționat și răspunsul lui @Drew Reese, capturezi eroarea prea devreme când React Query deja o face. Cred că o versiune simplificată a codului tău ar putea să facă problema mai ușor de văzut.
mutationFn: async () => {
const response = await api
.delete(`/admin/services/${item_id}/`)
.then((res) => { return res.data })
.catch((error) => {
// you're catching the error and returning the error response
return error.response.data
}
return response; // this will be error.response.data, mutationFn doesn't fail, thus call the onSuccess function.
}
