skip to Main Content

When API calls in React RTK query endpoints and receive response, but some times if the server throws an error, and API returns error – how to handle this in Axios its provide interceptor.

Can we implement interceptor in Redux RTK query or are there other alternatives to handle errors?

2

Answers


  1. Here’s an example how I have used axios interceptors with Redux-Toolkit Query with an axios base query function.

    import { createApi } from '@reduxjs/toolkit/query/react';
    import axios from 'axios';
    
    const axiosBaseQuery = () => {
      const instance = axios.create();
    
      // set common headers
      instance.defaults.headers.common.Accept = 'application/json';
      ...
    
      // eslint-disable-next-line no-unused-vars
      return async (args, { dispatch, getState }, extraOptions) => {
        ...
    
        // Add response inceptor error handler (e.g. the second arg)
        instance.interceptors.response.use(null, (error) => {
          if ([401, 403].includes(error.response.status)) {
            dispatch(actions.snackActions.warning({
              message: 'Authentication token expired.',
              timeToHide: 99 * 1000,
            }));
            const logoutUserState = API.endpoints.logoutUser.select({ fixedCacheKey: 'logoutUser' })(getState());
    
            if (!logoutUserState.isLoading) {
              dispatch(API.endpoints.logoutUser.initiate(undefined, { fixedCacheKey: 'logoutUser' }));
              dispatch(replace('/'));
            }
          }
          return Promise.reject(error);
        });
    
        // Run the query request using the axios instance
        try {
          const result = await instance({
            baseURL: /* your base URL here */,
            headers: {
              /* any dynamic runtime headers here */,
            },
            ...args,
          });
          return { data: result.data };
        } catch (axiosError) {
          const err = axiosError;
          return {
            error: {
              status: err.response?.status,
              data: err.response?.data || err.message,
            },
          };
        }
      };
    };
    
    const API = createApi({
      baseQuery: axiosBaseQuery(),
      tagTypes: /* your API slice tags here */,
      endpoints: (build) => ({
        ...
      }),
    });
    

    In the above example the code is simply looking for 401/403 error response status codes to log the user out, but you can run any business logic necessary for your specific use case in the error handler.

    Login or Signup to reply.
  2. Generally, you should not reach for Axios (your browser already ships with fetch, and axios doesn’t add a ton of functionality, but it does add a good bunch of bundle size – it’s only really necessary if you target very legacy platforms), but stay with the normal fetchBaseQuery. Instead of doing interceptors, you would just "wrap" a new function around the function created by fetchBaseQuery.

    const origBaseQuery = fetchBaseQuery(options);
    const myBaseQuery = (...args) => {
      // do things before if you want
      const result = origBaseQuery(...args)
      // do things after (like modifying result or returning something else) if you want
      // e.g.
      if ('error' in result) {
        console.log(result.error)
        // please don't do exactly this 😅 - but you get the idea
        return { data: "how gracefully we handled this!" }
      }
    
      return result
    }
    

    The concept of "interceptors" is really overblown if you also just can wrap your baseQuery instead.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search