Dijiflex
Dijiflex

Reputation: 603

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;

Upvotes: 2

Views: 11138

Answers (2)

Matt Sutkowski
Matt Sutkowski

Reputation: 921

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:

Upvotes: 6

Daniel Baldi
Daniel Baldi

Reputation: 920

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

Upvotes: 2

Related Questions