어수선한 우리앱에 react-query입히기

리액트만패는젊은이·2024년 6월 18일

ReactNative 공부기록

목록 보기
10/12
post-thumbnail

클라이언트 개발자라면 시대의 흐름에 막바지 일지라도 빠르게 탑승해야 한다고 생각한다. 처음 react-query를 접하고 사용했을때는 머가 먼지도 모르고 사용했지만 이제는 없어서는 안될것이 되어버렸다..

일단 ReactQuery가 무엇인지 부터 알아보자

React 또는 React-native Application에서 서버의 상태를 불러오고, 캐싱하며, 지속적으로 동기화하고 업데이트하는 작업을 도와주는 라이브러리라고 설명되어있다.

현재 우리의 앱에서는 @tanstack/react-query V4를 사용한다. 최신버전인V5가 있지만 V4가 손과 눈에 익어서 사용중이다. 핑계이긴하지만 개발의 속도가 가장 중요한 스타트업이다 보니 익숙한걸 사용하게 되는것같다.

설명보다는 아래 코드를 보면 더 이해가 빠르게간다.

--- get 호출 : useQuery
param : (key:string | Array<string>, api : any, param?: any, options?: any)

--- get 외 호출 : useMutation
param : (key: string | Array<string>, api : any, param?: any, option?: any)


const { isLoading, isError, data, error } = useQuery("getRapport", 
fetchRapportList, 
{
	refetchOnWindowFocus: false, // react-query는 focus가 달랃졋을때 재실행 여부 옵션
	retry: 0, // 실패시 재호출 몇번 할지
	onSuccess: data => {  // 성공시 호출  },
	onError: e => {
		// 실패시 호출 (401, 404 같은 error가 아니라 정말 api 호출이 실패한 경우만 호출됩니다.)
		// 강제로 에러 발생시키려면 api단에서 throw Error 날립니다.}
	enabled: true // true 가 되면 useQuery 수행 ( 동기적으로 처리 가능 )
});

<!--------------- update후에 get 다시실행 --------------------------------->
- React query 는 update 후에 get 함수를 간단히 재실행 가능
- mutation 함수가 성공할 때, unique key 로 맵핑된 get 함수를 invalidateQueries안에 넣는다
const queryClient = useQueryClient();

1.
const mutation = useMutation(postTodo, {
  onSuccess: () => {
    // postTodo가 성공하면 todos로 맵핑된 useQuery api 함수를 실행합니다.
    queryClient.invalidateQueries("todos");
  }
});
2.
const mutation = useMutation(editTodo, {
  onSuccess: data => {
    // data가 fetchTodoById로 들어간다
    queryClient.setQueryData(["todo", { id: 5 }], data);
  }
});

아래는 사용 예시이다

예시) 1개의 get 요청
// 토큰 검증 api
  const {isLoading, isError, data, refetch} = useQuery(
    "getToken",
    async () => await getAccessToken(auth.accessToken, auth.refreshToken),
    {retry: 0}
  );

예시) 1개 이상의 get 요청
const result = useQueries([
    {
      queryKey: ["getCoach", `${data}`],
      queryFn: () => getCoach(auth.id, data),
      enabled: !!data,
    },
    {
      queryKey: ["getRapportByCoach", `${data}`],
      queryFn: () => getRapportByCoach(auth.id, data),
      onSuccess: (res: any) => setMemberList(res.data),
      enabled: !!data,
    },
]);

예시) 여러개의 get 요청에대한 loading 처리
useEffect(() => {
    const loadingFinishAll = result.some((result) => result.isLoading);
    const Loading = loadingFinishAll || isLoading;
    if (Loading) {
      setLoading(true);
    } else {
      setLoading(false);
    }
  }, [result]);

예시) post 요청 
// 하나의 일정 생성 api
  const createSchedule = useMutation(
    ["createCoachSchedule"],
    () => createCoachSchedule(auth.accessToken, memberId, startDate, endDate),
    {
      onMutate: (variable) => { 
				console.log("onMutate", variable); 
				// variable : {loginId: 'xxx', password; 'xxx'}
			},
      onError: (error) => { console.log(error); },
      onSuccess: (res) => { console.log(res); },
      onSettled: () => { console.log("end"); },
    }
  );
profile
front-end-developer

0개의 댓글