Search code examples
reactjstypescriptrtk-query

How Can I Destructure error from is RTK Query Mutation Hook?


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();

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);
  }
}

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'.
below is updateProgramError when I log is as a whole on the console

{
  "status": 500,
  "data": {
    "status": "error",
    "message": "Something went very wrong!"
  }
}

enter image description here

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;


Solution

  • 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: