본문 바로가기
Front End

전역으로 로딩처리하기

by 코딩파이 2024. 10. 1.
똑똑한개발자 내부 코드리뷰의 외부 공개용 재정리 파일입니다. @24.02.20

 

개발을 진행할수록 로딩처리를 챙기게 되고, 또 관리 방법에 대해 고민이 많아집니다.

여러 방법이 있지만 DX와 속도 향상을 위해 전역 로딩도 종종 쓰곤 했는데요,

이전에 처리했던 두가지 방법을 소개합니다.

 

1. isMutating과  전역 로딩 컴포넌트로 처리하기

import React from 'react';
import { StyleSheet } from 'react-native';

import { Box, Spinner } from 'native-base';

import { QUERY_KEY } from '@constants/query-keys';
import { useIsFetching, useIsMutating } from '@tanstack/react-query';

const GlobalLoading = () => {
  const isFetching = useIsFetching({
    // 해당 옵션으로 loading 상태를 제외할 queryKey를 지정했습니다. 
    predicate: (query) => {
      if (query.queryKey[0] === QUERY_KEY.PRODUCT_IN_BOX.PRODUCT_REGISTER_LIST)
        return false;
      if (query.queryKey[0] === QUERY_KEY.PRODUCT.PRODUCT_REGISTER_LIST)
        return false;
      return true;
    },
  });

  const isMutating = useIsMutating();

  if (!!isFetching || !!isMutating)
    return (
      <Box
        style={StyleSheet.absoluteFill}
        justifyContent="center"
        alignItems="center"
      >
        <Spinner
          size="lg"
          color="black"
          accessibilityLabel="Loading posts"
          shadow="0"
        />
      </Box>
    );
  return null;
};

export default GlobalLoading;

 

 

대부분의 API는 React Query로 관리할 때 가장 손쉽게 적용할 수 있는 방법입니다.

React Query 로 호출되는 전역 상태를 읽고, 로딩 상태일 때 전역 스피너를 렌더링 해 줍니다.

만약에 특정 상황에서 전역 에러를 표시하지 않아야 한다면 예외처리도 손쉽게 할 수 있습니다.

 

2. Loading Context 사용하기 

1번 방법이 가장 빠르고 간단했지만, QueryKey나 Variables 만으로 제어할수 없는 상황이나,

버튼 자체에 로딩을 설정하는 등 다른 로딩 UI가 존재한다면 적용하기가 애매해잡니다.

그래서 이번엔 로딩 상태를 제어하는 hooks를 따로 분리하고,

React Query에서 가져온 로딩 상태를 이 hooks 로 전달하는 방식으로 구현했습니다.

전달받은 로딩 상태가 true라면 미리 작성된 로딩 UI가 동작합니다.

 

import { useContext, useEffect } from 'react';

import { LoadingContext } from './GlobalLoadingProvider';

const useGlobalLoadingEffect = (isLoading: boolean) => {
  const { endLoading, startLoading } = useContext(LoadingContext);

  useEffect(() => {
    if (isLoading) startLoading();
    else endLoading();
  }, [endLoading, isLoading, startLoading]);
};
export default useGlobalLoadingEffect;

 

const {
    data: interestCategoryListData,
    isFetching: isFetchingInterestCategoryListData,
  } = useGetInterestCategoryList({});

// 로딩 상태를 동적으로 손쉽게 처리할 수  있습니다.
  useGlobalLoadingEffect(
    isFetchingInterestCategoryListData
  );

 

이렇게 적용하면 각 페이지마다 로딩처리를 해주긴 해야하지만 

if (isLoading) return <Loading /> 과 같은 컴포넌트 리턴문보다 보기 깔끔하고,

로딩중인 컴포넌트 또한 Overlay 뒤편에 보이다보니 UX도 더 낫다고 생각합니다.