글쓰는 개발자

[React] ReactQuery 활용방법 본문

Development/Web

[React] ReactQuery 활용방법

세가사 2025. 8. 12. 00:26
반응형

 

 

[React] 구글 OAuth 소셜로그인 / JWT 사용 프론트엔드

[NestJS] 구글 소셜 로그인 OAuth2로 JWT 발급구글 로그인 OAuth 인증 등록1. 프로젝트 생성구글 클라우드 콘솔(https://console.cloud.google.com)에 접속합니다.현재 프로젝트 버튼을 클릭해서 새프로젝트를 생

gran007.tistory.com

 

React Query API 함수

React Query 에서는 서버 데이터의 조회를 위한 useQuery와 서버 데이터 업데이트하고 데이터를 다시 조회하기 위한 useMutate 함수를 제공합니다.

CRUD용 react query의 API 함수들을 하나의 파일에 정의해두고 불러내서 사용한다면 API의 활용도가 좋아지고 관리가 편해집니다.

03.query/01.project/index.ts 

import { useMutation } from "@tanstack/react-query";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import axios from "@/05.util/axios";

interface CreateProjectDto {
  readonly name: string;
}

interface UpdateProjectDto {
  readonly id: number;
  readonly name: string;
}

interface DeleteProjectDto {
  readonly id: number;
}

export function useProjectListQuery() {
  return useQuery({
    queryKey: ['project', 'list'],
    queryFn: async () => {
      return await axios.get('/project/user');
    },
  });
};

export function useAddProjectQuery(clear: Function) {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: async (dto: CreateProjectDto) => {
      return await axios.post('/project', dto);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({
        queryKey: ['project', 'list'],
      });
      clear();
    }
  });
};

export function useUpdateProjectQuery(clear: Function) {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: async (dto: UpdateProjectDto) => {
      return await axios.patch('/project', dto);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({
        queryKey: ['project', 'list'],
      });
      clear();
    }
  });
};

export function useDeleteProjectQuery(clear: Function) {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: async (dto: DeleteProjectDto) => {
      return await axios.delete('/project', { data: dto })
    },
    onSuccess: () => {
      queryClient.invalidateQueries({
        queryKey: ['project', 'list'],
      });
      clear();
    }
  });
};

 

하나의 예시로 useAddProjectQuery를 보면 useMutation을 사용해 project를 추가하는 API를 호출한 뒤 API 콜이 성공하면 onSuccess 함수에서 invalidateQueries를 통해 등록된 queryKey로 useQuery로 프로젝트의 리스트를 재호출 할수 있도록 합니다.

 

React Query / useQuery API 사용

useQuery를 사용한 API를 이용할때는 리턴값으로 isLoading, error, data를 받을 수 있습니다. 한번 호출된 useQuery 함수는 react에서 주기적으로 호출되고 로딩이 끝나지 않았을때는 isLoading이 에러가 났을 때는 error값이 결과를 잘 받아와지면 data를 각각 제공합니다. 따라서 각각의 파라미터별 처리를 해주는 부분이 필요합니다.

먼저 isLoading을 처리하기 위해서 react loading indicator를 설치해서 사용합니다. 

npm i react-loading-indicators

 

import style from './style.module.css';
import { useProjectListQuery } from '@/03.query/01.project';
import { Riple } from "react-loading-indicators";


export default function Project() {
    const { isLoading, error, data } = useProjectListQuery();

    return (
        <>
            <div className={style.body}>
                ...
            </div>
            {isLoading &&
              <div className={style.loading}>
                <Riple size='small' color='#2F7AE5' />
              </div>
            }
        </>
    )
}

이러면 API가 loading 중일때는 아래와 같이 인디케이터가 나타납니다.

 

이제 에러를 처리하기 위해 에러가 undefined나 null이 아닐 경우의 화면을 그려줍니다.

export default function Project() {

...
   if (error) {
        return (
            <div className={style.body}>
                <div className={style.error}>
                    {error.message}
                </div>
            </div>
        )
   }
   
   return (
   ...

이 처럼 중간에 error를 감지해 component를 리턴해주면 에러가 존재할 때 최하단의 다른 화면이 그려지기전에 이를 감지하여 먼저 에러 관련 화면을 그려줍니다.

 

마지막으로 로딩도 끝나고 에러도 나지 않을 경우에는 react component의 값으로 활용하여 데이터를 그려주면 됩니다.

{data?data.map((project: Project, index: number) => (
    <div key={index} className={style.item}>
        <div className={style.body1}>{project.name}</div>
        <div className={style.body2}>{project.user.name}</div>
    </div>
))}

 

React Query / useMutate API 사용

useMutate를 사용한 react query 의 함수의 경우 먼저 onSuccess에서 호출할수 있는 clear 함수를 넘겨준뒤 생성된 객체의 mutate함수를 호출해 mutationFn에 지정된 axios 통신함수를 이용해 데이터 수정 요청 API를 호출하고 결과를 refresh 하게할수 있습니다.

// 정의
function useAddProjectQuery(clear: Function) {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: async (dto: CreateProjectDto) => {
      return await axios.post('/project', dto);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({
        queryKey: ['project', 'list'],
      });
      clear();
    }
  });
};

export default function example() {
... // 사용예시
    const addData = useAddProjectQuery(clear);

    const onClickSave = (name) => {
        addData.mutate({ name });
    }
...
}

 

반응형