import { AxiosError } from 'axios'; import { useLocation, useNavigate } from 'react-router'; import { SearchParamKeys } from '../lib/constants'; import { useQueryMessage } from './useQueryMessage'; import { QueryMessageCode, QueryMessageType } from '../lib/QueryMessages'; import { useCallback } from 'react'; import { displayForbiddenErrorToast, displayNetworkErrorToast, displayUnexpectedErrorToast } from '../lib/toasts'; export enum ResponseErrorToastId { NetworkError = 'network-error', } export type DefaultResponseErrorHandlerOptions = { disableUnauthorizedHandling?: boolean; disableHandleUnexpectedErrors?: boolean; disableIgnoreCanceledRequests?: boolean; }; /** * * @param err error value * @returns {boolean} true if the error was handled, false otherwise */ export function useResponseErrorHandler(): { defaultResponseErrorHandler: typeof defaultResponseErrorHandler; } { const navigate = useNavigate(); const location = useLocation(); const { toSearchParamQueryMessage } = useQueryMessage(); const defaultResponseErrorHandler = useCallback( (err: unknown, options?: DefaultResponseErrorHandlerOptions): boolean => { if (!(err instanceof AxiosError) && !options?.disableHandleUnexpectedErrors) { displayUnexpectedErrorToast(); return true; } if (!(err instanceof AxiosError)) return false; if (err.message === 'canceled') { // request was aborted, ignore but return true to indicate it was handled return !options?.disableIgnoreCanceledRequests; } if (err.message === 'Network Error') { displayNetworkErrorToast(); return true; } // handle 401 Unauthorized globally if (err.status === 401 && !options?.disableUnauthorizedHandling) { // store current path for redirect after login const currentPath = location.pathname + location.search; const searchParam = new URLSearchParams(); searchParam.set(SearchParamKeys.Redirect, currentPath); searchParam.set(SearchParamKeys.Message, toSearchParamQueryMessage(QueryMessageCode.SessionExpired, QueryMessageType.Info)); navigate(`/login?${searchParam.toString()}`); return true; } if (err.status === 403) { displayForbiddenErrorToast(); return true; } return false; }, [location, navigate, toSearchParamQueryMessage] ); return { defaultResponseErrorHandler }; }