typescript - Tanstack React Query useMutation πάντα Αληθές στο 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;
Αυτή τη στιγμή πειραματίζομαι με το react-query στο έργο μου.
Αντιμετωπίζω ένα πρόβλημα με τη διαχείριση σφαλμάτων μέσα στην μετάλλαξή μου.
Όταν ελέγχω την καρτέλα δικτύου, μπορώ να δω ότι ο διακομιστής αποκρίνεται είτε με κωδικό κατάστασης 400 είτε 500, που υπέθεσα ότι θα προκαλούσε στο axios να ρίξει ένα σφάλμα, ενεργοποιώντας τη καθορισμένη συνάρτηση onError.
Ωστόσο, η συνάρτηση onSuccess καλείται πάντα.
Τι θα μπορούσα να παραβλέπω; Ευχαριστώ εκ των προτέρων.
Απάντηση #1
Υποψιάζομαι ότι το πρόβλημα εδώ είναι ότι η συνάρτηση μετάλλαξής σας πιάνει τα σφάλματα που πετάγονται πριν το hook useMutation μπορέσει να τα χειριστεί για να καλέσει οποιονδήποτε παρεχόμενο χειριστή 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);
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: () => {
// ...
},
});
Απάντηση #2
Όπως ανέφερε η απάντηση του @Drew Reese, καταγράφεις το σφάλμα νωρίτερα από ότι πρέπει όταν το react query το χειρίζεται ήδη. Νομίζω ότι μια απλουστευμένη έκδοση του κώδικά σου μπορεί να κάνει το πρόβλημα πιο εύκολο να φανεί.
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.
}
