
클라이언트 개발자라면 시대의 흐름에 막바지 일지라도 빠르게 탑승해야 한다고 생각한다. 처음 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"); },
}
);