axios instance에 에러 핸들링 로직 추가하기 + next

Yechan Jung·2024년 5월 23일
0

개발

목록 보기
3/6
post-thumbnail

발단

에러가 뜨면 네트워크 에러 모달을 부르자, 그런데 쉽게

useEffect(() => {
  const res = await getFunc();
  setSomeState(res.data);
}

axios instance에서 오류를 핸들링하여 별도의 try-catch 로직 없이 API Call을 사용하면 모달이 불러지게 하려고 하였다.


axios instance에 interceptor을 설정하여 에러를 가져오는 도중 에러 모달을 띄워보자.

// someAxiosInstance.ts
const someAxiosInstance = axios.create()

someAxiosInstance.interceptors.response.use(
  (response: AxiosResponse) => {
    return response;
  },
  (error) => {
    setOpenModal(open) // ERROR
    return Promise.reject(error);
  },
);

하지만 위와 같은 로직은 불가능하다.

Error: Invalid hook call. Hooks can only be called inside of the body of a function component.

상태관리 라이브러리(jotai, recoil 등)의 커스텀훅은 함수 컴포넌트 내부에서 불러야 하기 때문.
그렇기에 ContextAPI를 사용하여 커스텀 오류 처리 로직을 만듬

// globalErrorProvider.tsx
const GlobalErrorProvider = ({ children }) => {
  const [error, setError] = useState<string | null>(null);

  const clearError = useCallback(() => setError(null), []);
  const setErrorHandler = useCallback((err: string) => setError(err), []);

  const contextValue = useMemo(
    () => ({ setError: setErrorHandler, clearError, error }),
    [setErrorHandler, clearError, error],
  );

  return (
    <GlobalErrorContext.Provider value={contextValue}>
      {children}
    </GlobalErrorContext.Provider>
  );
};

일반적인 Provider 구조와 크게 다르지 않다.
contextValue에 setErrorHandler, clearError, error 을 넣어 사용하였다.

// createAxiosInstance
let setGlobalError: (error: string) => void;

export const setGlobalErrorHandler = (handler: (error: string) => void) => {
  setGlobalError = handler;
};

const createAxiosInstance = (config: AxiosRequestConfig) => {
  const instance = axios.create(config);

  instance.interceptors.response.use(
    (response: AxiosResponse) => {
      return response;
    },
    (error) => {
      setGlobalError("Failed to fetch data. Please try again later.");
      return Promise.reject(error);
    },
  );

  return instance;
};

export { createAxiosInstance };

이제 원래 계획대로 axios instance 에서 interceptor를 사용.

결론

try-catch 로직을 API마다 감싸서 각 오류에서 에러 모달을 띄우지 않아도 해당 인스턴스를 사용하는 모든 API Call이 오류시 오류 모달을 여는 것을 확인하였다.

NextJS의 Static Props에서 fetch하는 경우

NextJS의 SSR을 이용한 페이지의 경우 ContextAPI 정의 전에 fetch 함수가 불러지므로 위의 방식이 사용이 불가능하여 아래 와 같이 custom error 핸들링 로직을 추가함

// ssrPage/index.tsx

interface SsrPageProps {
  origProps: OrigPropsType
  error?: string;
}

export default function SsrPage({ error }: SsrPageProps) {
  return <SsrPage error={error} />;
}

export const getServerSideProps: GetServerSideProps = async () => {
  try {
    // fetch 함수
    return {
      props: {
        origProps
      },
    };
  } catch (error) {
    return {
      props: {
        error: "Failed to fetch.",
      },
    };
  }
};

function SsrPage({
  origProps,
  error,
}){

  if(error) {
    return <ErrorDialog>{error}<ErrorDialog>
  }

  return {
    // original Page
  }

}
profile
꿈꾸는 개발자

0개의 댓글