React Query를 처음 사용할 때 Key에 대한 고민을 깊게 하지 않은 상태로 시작했다.
그러다보니 이런식으로 사용 했다
유저의 이름을 검색하면 입력 할 때마다 결과를 list로 목록을 그리는 useQuery 이다
export const useFetch = (key: any, method: string, url: string, param?: any, option?: any) => {
return useQuery<any, AxiosError, IResult>(key, () => fetchFn(method, url, param), {
...option
});
}
useFetch(['getUserNm', deboundStr], 'get', `/usr/search/${deboundStr}`, null, {
onSuccess: (res: IResult) => {
if (res.result === Consts.SUCCESS) {
setOnUserNmList(true);
}
},
});
처음엔 ['getUserNm', deboundStr]
이런식으로 사용하다가 검색화면에서 검색필터가 5개 이상인 페이지는 어떻게 해야하나 고민이였다.
그래서 변경한게 검색필터를 Array로 만들어서 넣었다
['getUserNm', filters]
filters는 [키워드, 셀렉트박스선택값, 셀렉트박스선택값2,..., 페이지번호, 한페이지에 보여줄 Row수]
그런데 이렇게 하다보니 또 문제가 생겼다.
Array의 몇번째 인덱스가 어떤 검색조건값인지 기억해야하고 Key Array에 순서가 달라지면 새로운 Query로 인식한다는거다.
그래서 Object로 변경했다.
//asis filters = ['','Y','1','30']
//to-be
const filters:IFilters = {
keyword: '', // 검색어
useYn: 'Y', // 사용여부 셀렉트박스
page:1, // 페이지 번호
pagePerRow: 30, // 한 페이지에 보여줄 row
}
그런데 여기서 문제가 2개가 더 있어서 해결했다.
검색조건의 onChange에 filters에 set을 하고 있어서
검색이 바로바로 되는것이였다.
검색버튼을 눌렀을 때만 검색이 되어야하니 state를 하나 더 만들었다.
input이나 SelectBoxon에 Change를 담는 state는 filters를 이용하고 query key에는 fetchKeys라는 state를 만들어서 검색버튼을 클릭했을 때 setFetchKeys를 이용해서 새롭게 fetch를 진행했다.
['getUserNm', fetchKeys]
query keys의 이름에 규칙성이 없었다.
그러다보니 나중에 useMutation 후에 onSuccess 콜백에서queryClient.invalidateQueries(지정한key) 할 때 key의 규칙성이 필요했다.
그러다가 이 블로그를 봤다
https://tkdodo.eu/blog/effective-react-query-keys
정독 한번 하고 바로 변경했다.
export const Userkeys = {
all: ['user'] as const,
lists: () => [...Userkeys.all, 'list'] as const,
list: (filters: IFilters) => {
return [...Userkeys.lists(), filters] as const
},
details: () => [...Userkeys.all, 'detail'] as const,
detail: (id: string) => [...Userkeys.details(), id] as const,
};
useFetch(Userkeys.list(filters),'get', url, config)
Factory를 통해 키를 생성하니 키의 규칙성이 생기고
(오타방지, 네이밍고통해방)
invalidateQueries를 할 때도 user 의 모든 query를 무효화한후에 다시 불러올수도 있고 user의 특정 query만 할 수 도 있다.
모든 user 의 query 무효화 invalidateQueries(['user'])
user 목록만 무효화 invalidateQueries(['user','list'])
setQueryData를 써도 되지만 데이터종류도 많고 fetch후에 callback에서 해야할 작업이 많아서 invalidateQueries를 사용했습니다
#Ref
https://react-query-v3.tanstack.com/guides/query-invalidation
https://tkdodo.eu/blog/effective-react-query-keys