query key factory의 장점

const courseKeys = {
  all: ['course'] as const,
  detail: (courseId: number) => ['course', courseId] as const,
  lectureList: (courseId: number, params: { sort: string }) => [
    'course',
    courseId,
    'lectures',
    params,
  ] as const,
};

// 쿼리 호출 시
const courseDetailQueryKey = courseKeys.detail(123);
const lectureListQueryKey = courseKeys.lectureList(123, { sort: 'new' });

query key 분류

const course = '<https://examaple.com/course>';
const courseDetail = '<https://examaple.com/course/:id>';

const courseQueryKeys = ['course'];
const courseDetailsQueryKeys = (id) => ['course', id];

const courseLecture =
'<https://examaple.com/course/:id/lecture/:id?sort=new&type=selling&page=0&size=10>';

  1. url에 포함된 연관있는 도메인명: 'course', 'lecture'
  2. id: 'courseId', 'lectureId'
  3. query params: 'sort', 'type', 'page', 'size'

query key를 정리

const courseLecture = '<https://examaple.com/course/1/lecture/2?sort=new&type=selling&page=0&size=10>';
const courseId = 1;
const lectureId = 2;
const queryParams = {
  sort: 'new',
  type: 'selling',
  page: 0,
  size: 10,
};

const courseLectureQueryKeys = (courseId, lectureId, queryParams) => [
  'course',
  courseId,
  'lecture',
  lectureId,
  queryParams,
];

쿼리키 객체화

const courseKeys = {
  all: ['course'] as const,
  detail: (courseId: number) => ['course', courseId] as const,
  lectures: (courseId: number) => [...courseKeys.detail(courseId), 'lecture'] as const,
  // queryParams의 경우 안의 값이 optional 일지 아닐지에 대해 꼭 안넘겨 주어도 될 수 있습니다.
  lectureDetail: (courseId: number, lectureId: number, queryParams: LectureParams) =>
    [...courseKeys.lectures(courseId), lectureId, { queryParams }] as const,
};

Query Options의 등장

<aside> 💡

기존 v4과 다르게 v5는 여러 인자들이 객체로 넘기게끔 변했다는 점 입니다.

</aside>

v5로 구조를 잡는다고 한다면 queryOptionsinfiniteQueryOptions 두 개를 사용해서 구조화 시키는게 가장 좋은 방법이라고 생각 합니다. ( infiniteQueryOptions === useInfinityQuery )

import { queryOptions } from '@tanstack/react-query';

import type { CourseListParams } from '@/types/course/remote';

const courseQueries = {
  allKeys: ['course'] as const,
  all: () =>
    queryOptions({
      queryKey: courseQueries.allKeys(),
      queryFn: () => getCourse(),
    }),
  listKeys: (params: CourseListParams) => [...courseQueries.allKeys(), params],
  list: (params: CourseListParams) =>
    queryOptions({
      queryKey: courseQueries.listKeys(params),
      queryFn: () => getCourseList(params),
    }),
};