I am using redux toolkit query for my data fetching API. The problem is I am having is error handling redux toolkit returns an error property from the query hook. So the error that is returned from the server is an object with nested data and what trying to access it I get a typescript error when trying to access the data from the error object.
below is how I am declaring my mutation hook
const [updateProgram, {
isLoading: isUpdatingProgram,
error: updateProgramError
}] = useUpdateProgramMutation();
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
below is how I try to access the error in my code.
onSubmit = {
async(values, {
setSubmitting
}) => {
await updateProgram({ ...values,
id: 'programData.data._id'
});
refetch();
if (updateProgramError) {
enqueueSnackbar('Test message', {
variant: 'error'
});
console.log(updateProgramError?.data?.message);
}
setSubmitting(false);
}
}
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
now the typescript error I am getting is as below. Not that I able to console.log(updateProgramError) and is the data in the console
Property 'data' does not exist on type 'FetchBaseQueryError | SerializedError'.
Property 'data' does not exist on type 'SerializedError'.
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
below is updateProgramError when I log is as a whole on the console
{
"status": 500,
"data": {
"status": "error",
"message": "Something went very wrong!"
}
}
<iframe name="sif4" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
below is how I have implemented useUpdateProgramMutation().
import { ndovuAPI } from './ndovuAPI';
export const ndovuProgramsAPI = ndovuAPI.injectEndpoints({
endpoints: builder => ({
getProgramById: builder.query({
query: (id: string) => `/programs/${id}`,
providesTags: ['Programs']
}),
getAllPrograms: builder.query({
query: queryParams => ({ url: `/programs/`, params: queryParams }),
providesTags: ['Programs']
}),
registerProgram: builder.mutation({
query: body => ({
url: '/programs',
method: 'POST',
body
}),
invalidatesTags: ['Programs']
}),
updateProgram: builder.mutation({
query: body => ({ url: `/programs/${body.id}`, method: 'PATCH', body }),
invalidatesTags: ['Programs']
})
}),
overrideExisting: true
});
// Export hooks for usage in functional components
export const { useGetProgramByIdQuery, useGetAllProgramsQuery, useUpdateProgramMutation } = ndovuProgramsAPI;
<iframe name="sif5" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
The code as you have it written will not work the way you want. You can't reference the error from the hook inside of an onSubmit handler like that. What you'll want to do is this:
const onSubmit = async (values) => {
try {
// unwrapping will cause data to resolve, or an error to be thrown, and will narrow the types
await updateProgram({
...values,
id: 'programData.data._id'
}).unwrap();
// refetch(); // you should most likely just use tag invalidation here instead of calling refetch
} catch (error) {
// error is going to be `unknown` so you'll want to use a typeguard like:
if (isMyKnownError(error)) { // add a typeguard like this
enqueueSnackbar('Test message', {
variant: 'error'
});
} else {
// You have some other error, handle it differently?
}
}
}
References:
CodePudding user response:
From what I can infer from this TS error, the type of updateProgramError
seems like an union of types 'FetchBaseQueryError'
, 'SerializedError'
and possibly other types, which means that TS only assumes that you can safely access this data
property after ensuring that data
exists in the object.
In other words, TS does not know which of these types updateProgramError
will be unless you do some checking to ensure that.
if (updateProgramError) {
enqueueSnackbar('Test message', {
variant: 'error'
});
if ('data' in updateProgramError) console.log(updateProgramError.data.message);
}