Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define global error handler in RTK Query

I have api defined in RTK query in a "standard" way like

export const myApi = createApi({
  reducerPath: "myApi",
  baseQuery: fetchBaseQuery({
    baseUrl: "https://some-url",
  }) as BaseQueryFn<string | FetchArgs, unknown, APIError>,
  endpoints: (builder) => ({
    getX: builder.query<ResponseX, null>({
      query: () => ({
        url: "getX",
      }),
      async onQueryStarted: (args, { queryFulfilled }) => {
        try {
          const { data } = await queryFulfilled
        } catch (err) {
          // handle error for getX here
        }
      }
    }),
    getY: builder.query<ResponseY, null>({
      query: () => ({
        url: "getY",
      }),
      async onQueryStarted: (args, { queryFulfilled }) => {
        try {
          const { data } = await queryFulfilled
        } catch (err) {
          // handle error for getY here
        }
      }
    }),
    ...
  })
})

I know how to handle errors for individual endpoints, but is there a way to define a global error handler capturing errors from all endpoints in one single handler/function?

like image 800
baa2w Avatar asked Oct 12 '25 12:10

baa2w


1 Answers

If all you want is for each query/mutation to have the "same" error response handling you could define a custom onQueryStarted function that awaits the query/mutation to settle and trigger the toast upon errors.

const onQueryStartedErrorToast = (args, { queryFulfilled }) => {
  try {
    await queryFulfilled;
  } catch (error) {
    // handle error here, dispatch toast message
  }
};
export const myApi = createApi({
  reducerPath: "myApi",
  baseQuery: fetchBaseQuery({
    baseUrl: "https://some-url",
  }) as BaseQueryFn<string | FetchArgs, unknown, APIError>,
  endpoints: (builder) => ({
    getX: builder.query<ResponseX, null>({
      query: () => ({
        url: "getX",
      }),
      onQueryStarted: onQueryStartedErrorToast
    }),
    getY: builder.query<ResponseY, null>({
      query: () => ({
        url: "getY",
      }),
      onQueryStarted: onQueryStartedErrorToast
    }),
    ...
  }),
});

This pattern would work until you have an endpoint that you want to toast errors for and do other things. Here you could write one-off onQueryStarted handlers that do exactly what you want.

If it's the case that no matter the endpoint you want to toast errors, then you could write your own custom base query function that reads any errors as the "pass through" and issue the toasts.

Example:

const baseQuery = (baseQueryOptions) => async (args, api, extraOptions) => {
  const result = await fetchBaseQuery(baseQueryOptions)(args, api, extraOptions);

  if (result.error) {
    // dispatch toast message
  }

  return result;
};
export const myApi = createApi({
  reducerPath: "myApi",
  baseQuery: baseQuery({
    baseUrl: "https://some-url",
  }) as BaseQueryFn<string | FetchArgs, unknown, APIError>,
  endpoints: (builder) => ({
    getX: builder.query<ResponseX, null>({
      query: () => ({
        url: "getX",
      }),
      async onQueryStarted: (args, { queryFulfilled }) => {
        try {
          const { data } = await queryFulfilled;
        } catch (err) {
          // handle error for getX here
        }
      }
    }),
    getY: builder.query<ResponseY, null>({
      query: () => ({
        url: "getY",
      }),
    }),
    ...
  }),
});
like image 143
Drew Reese Avatar answered Oct 14 '25 21:10

Drew Reese