useQuery의 queryKey를 어떤 방식으로 관리하시나요? #7
-
고민
코드export const userQueries = {
ageQueryKey: () => ['age'],
age: () => {
return queryOptions({
queryKey: userQueries.ageQueryKey(),
queryFn: async () => await fetchUserAge(),
});
},
contactQueryKey: () => ['contact'],
contact: () => {
return queryOptions({
// PROBLEM: age와 동일한 키를 사용
queryKey: userQueries.ageQueryKey(),
queryFn: async () => await fetchUserContact(),
});
},
}; 참고 자료
|
Beta Was this translation helpful? Give feedback.
Replies: 8 comments 2 replies
-
저의 경우 특정 도메인을 나타내기 위한 상수값만 관리를 하면 되기도 하구요 |
Beta Was this translation helpful? Give feedback.
-
저도 queryKey 값을 토대로 캐싱하고, (이런 식으로요!) export const QUERY_KEYS = {
GENERAL: {
PLANS: {
INDEX: ['plans'],
},
PLAN: {
INDEX: (planId: number) => ['plan', planId],
},
PLACES: {
INDEX: ['places'],
},
PLACE: {
INDEX: ['place']
},
},
} 또한, 캐싱된 값은 그래서, Tanstack Query에서 제공하는 따라서, 각
queryClient.setMutationDefaults(MUTATION_KEYS.PLAN.CREATE.key, {
mutationFn: MUTATION_KEYS.PLAN.CREATE.fc,
onSuccess(data, variables, context) {
queryClient.invalidateQueries({ queryKey: QUERY_KEYS.USER.PLANS.INDEX })
},
})
mutation.mutate(newTodo, {
onSuccess() {
setState(어떤 값으로 바꾼다)
router.push(어디로 이동한다)
}
}); 이렇게 사용하니, 참고 (블로그) |
Beta Was this translation helpful? Give feedback.
-
저는 Axios.instance ➠ class Fetcher ➠ class Request ➠ useAdaptor ➠ Component의 흐름으로 각각의 데이터 처리 과정을 추상화해서 쓰고 있습니다. 이 중에서 쿼리 키 관리는 class Request 의 책임으로 두고 있어요. export class BookRequest extends Fetcher {
constructor() {
super();
}
queryKey = ["book"];
getBookByIsbn(isbn13: string) {
return {
queryKey: [...this.queryKey, isbn13],
queryFn: this.fetcher<Item>(`/aladin/detail?isbn=${isbn13}`),
enabled: !!isbn13,
};
}
...
} 만약 도메인이 커질 경우에는 해당 도메인의 메인이 되는 class Request를 컴포지션 하는 식으로 쿼리 키를 넘겨주고 있습니다. export class ArticleRequest extends Fetcher {
queryKey: ["article"]
...
}
export class ArticleLikeRequest extends Fetcher {
queryKey: Array<string>
constructor(queryKey: string) {
super();
const articleRequest = new ArticleRequest();
this.queryKey = [ ...articleRequest.queryKey, "like" ]; // queryKey 확장
}
}
checkArticleLike(reportId: string) {
return {
queryKey: [...this.queryKey, reportId],
queryFn: this.fetcher<{ isLiked: boolean }>(`/article/${reportId}/like`),
};
}
...
} useAdaptor 훅에서는 각 엔드포인트에 따른 클래스를 호출에서 사용하고 있습니다. export const useCheckArticleLikeAdaptor(reportId: string) {
const articleLikeRequest = new ArticleLikeRequest()
const { data } = useQuery(articleLikeRequest.checkArticleLike(reportId: string))
…
} 아주 대규모의 프로젝트에서도 이러한 패턴이 유효할지는 잘 모르겠습니다만, 적당한 수준의 프로젝트에서는 아직까지는 꽤 괜찮다고 생각합니다 :) |
Beta Was this translation helpful? Give feedback.
-
query options api를 이용해서 query-factory를 만들어서 사용하고 있습니다. |
Beta Was this translation helpful? Give feedback.
-
저도 개인적으로 @lukemorales/query-key-factory를 자주 사용하고있습니다. |
Beta Was this translation helpful? Give feedback.
-
별도의 라이브러리를 사용하지는 않았고, tkdodo 블로그에서 제안하는 factory 패턴을 참고해서, 각 기능마다 생성하면서 사용했었던 경험이 있어요. https://tkdodo.eu/blog/effective-react-query-keys#use-query-key-factories |
Beta Was this translation helpful? Give feedback.
-
위에서 언급된 npm 패키지는 좋긴한데 간단하게 사용하기에는 약간 복잡하고 마지막 업데이트가 1년이 넘은 상황이라(v5이전) 약간의 이슈도 존재합니다 리액트 쿼리 제작자가 작성한 인강?문서?(query.gg)에도 예시로 const todoKeys = {
all: () => ['todos'],
allLists: () => [...todoKeys.all(), 'list'],
list: (sort) => [...todoKeys.allLists(), { sort }],
} 이런 단순한 객체 형태나 const todoQueries = {
all: () => ({ queryKey: ['todos'] }),
allLists: () => ({
queryKey: [...todoQueries.all().queryKey, 'list']
}),
list: (sort) => ({
queryKey: [...todoQueries.allLists().queryKey, sort],
queryFn: () => fetchTodos(sort),
staleTime: 5 * 1000,
}),
allDetails: () => ({
queryKey: [...todoQueries.all().queryKey, 'detail']
}),
detail: (id) => ({
queryKey: [...todoQueries.allDetails().queryKey, id],
queryFn: () => fetchTodo(id),
staleTime: 5 * 1000,
}),
} 쿼리옵션과 결합하는 형태까지만 가이드중이지 뭔가 더 특별하고 복잡한 내용은 언급하지 않기때문에 너무 복잡하게 생각 안하고있습니다 |
Beta Was this translation helpful? Give feedback.
-
저도 위에서 많이 언급해주신 Query Factory와 queryOptions를 같이 결합하는 패턴으로 사용하고 있습니다 |
Beta Was this translation helpful? Give feedback.
저의 경우
/~https://github.com/lukemorales/query-key-factory 라이브러리를 사용해서 관리하고 있는데요.
queryKeys를 관리하는 특정 도메인을 모체로 하는 객체를 만들고 하위의 all, list, detail 등 세부적인 API에 따라 나눈 후 사용하고 있습니다.
특정 도메인을 나타내기 위한 상수값만 관리를 하면 되기도 하구요
inferQueryKeyStore 메소드를 통해 특정 쿼리의 타입을 추출하여 타입 체크도 가능합니다!!