๋ฐ˜์‘ํ˜•

React Query์—์„œ ์ œ๊ณตํ•˜๋Š” useQuery, useMutation์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋ฉด ํ•ญ์ƒ ์ฟผ๋ฆฌํ‚ค์™€ ์ฟผ๋ฆฌ ํ•จ์ˆ˜๋ฅผ ์ง€์ •ํ•ด์•ผ ํ•˜๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€์ด ์žˆ๋‹ค. API ์œ ํ˜•์— ๋”ฐ๋ผ Base Query|Mutation ์ปค์Šคํ…€ ํ›…์„ ๋งŒ๋“ค์–ด ๋‘๊ณ  ์‚ฌ์šฉํ•˜๋ฉด ์ฟผ๋ฆฌํ‚ค์™€ ์ฟผ๋ฆฌ ํ•จ์ˆ˜๋ฅผ ์ผ์ผ์ด ์ง€์ •ํ•˜์ง€ ์•Š๊ณ  ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์ข‹๋‹ค.

 

ํ•˜์ง€๋งŒ ์ปค์Šคํ…€ ํ›…์„ ๋งŒ๋“ค ๋•Œ ์ฟผ๋ฆฌ ํƒ€์ž…์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฐ์ดํ„ฐ๊ฐ€ unknown, any์ธ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„์„œ ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๋Š”์ง€ ์•Œ๊ธฐ ์–ด๋ ต๋‹ค. ์ฟผ๋ฆฌ ํƒ€์ž…์€ ๋Œ€๋ถ€๋ถ„ ์ œ๋„ค๋ฆญ์œผ๋กœ ๋˜์–ด ์žˆ๋Š”๋ฐ ์ด๋ฅผ ์ž˜ ์‚ฌ์šฉํ•˜๋ฉด ํƒ€์ž…์„ ๋ณด์žฅ ๋ฐ›์œผ๋ฉด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋‹ค.

 

useQuery


์ œ๋„ค๋ฆญ ํƒ€์ž… ํ†บ์•„๋ณด๊ธฐ โšก๏ธ

export declare function useQuery<
  TQueryFnData = unknown,
  TError = unknown,
  TData = TQueryFnData,
  TQueryKey extends QueryKey = QueryKey // string | readonly unknown[];
>

 

โถ TQueryFnData : ์ฟผ๋ฆฌ ํ•จ์ˆ˜ ๋ฆฌํ„ด ํƒ€์ž… (AxiosResponse<T> ๋“ฑ)

โท TError : ์ฟผ๋ฆฌ ํ•จ์ˆ˜ ์—๋Ÿฌ ํƒ€์ž… (AxiosError ๋“ฑ)

const { data, error } = useQuery<number, AxiosError>("todo", getTodo);
// data ํƒ€์ž… : number | undefined
// error ํƒ€์ž… : AxiosError | null

 

โธ TData : select ํ•จ์ˆ˜๋กœ ์ฟผ๋ฆฌ ํ•จ์ˆ˜ ๋ฆฌํ„ด๊ฐ’์„ ๊ฐ€๊ณตํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์ตœ์ข… ๋ฆฌํ„ด ํƒ€์ž…. ๊ธฐ๋ณธ๊ฐ’ TQueryFnData

TQueryFnData is the data returned from your query function, and TData is the eventual data. The eventual data can be different from the query function data when using select for example. — TanStack

 

const { data } = useQuery<Todo[], AxiosError, number>("todos", getTodos, {
  select: (todos) => todos.length,
});
// select ํ•จ์ˆ˜๊ฐ€ number(todos.length) ํƒ€์ž…์„ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ
// TData(3๋ฒˆ์งธ ์ œ๋„ค๋ฆญ ํƒ€์ž…) ํƒ€์ž…๋„ number ํƒ€์ž…์œผ๋กœ ์ง€์ •ํ•ด์ค€๋‹ค

 

โน TQueryKey : ์ฟผ๋ฆฌ ํ‚ค ํƒ€์ž…. ๊ธฐ๋ณธ๊ฐ’ ๋ฌธ์ž์—ด ํ˜น์€ ๋ฐฐ์—ด. 

์ฟผ๋ฆฌํ‚ค ๋ฐฐ์—ด ๊ฐ ์š”์†Œ์— ์–ด๋–ค ํƒ€์ž…์ด ๋“ค์–ด๊ฐˆ์ง€ TQueryKey ํƒ€์ž…์— ์ง์ ‘ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. 

useQuery<Todo[], AxiosError, Todo[], [string, number]>(["todos", id], getTodo);

 

์ฐธ๊ณ ๋กœ QueryKey ํƒ€์ž…์€ ๋ฌธ์ž์—ด ํ˜น์€ ๋ฐฐ์—ด์ด์ง€๋งŒ ์ฟผ๋ฆฌ ํ•จ์ˆ˜์˜ context ์ธ์ž์—” ํ•ญ์ƒ ๋ฐฐ์—ด๋กœ ์ „๋‹ฌ๋œ๋‹ค. ์ฆ‰ ์ฟผ๋ฆฌํ‚ค๋ฅผ ๋ฌธ์ž์—ด๋กœ ์ง€์ •ํ•ด๋„ ์ฟผ๋ฆฌ ํ•จ์ˆ˜์—” ํ•ญ์ƒ ๋ฐฐ์—ด๋กœ ์ „๋‹ฌ๋˜๋Š” ๊ฒƒ. e.g. 'todo'['todo']

queryFn: (context: QueryFunctionContext) => Promise<TData>

 

Base Query ์ปค์Šคํ…€ ํ›…

ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์—†์„ ๋•Œ

ํ›…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ณณ์—์„œ ์ฟผ๋ฆฌ ์˜ต์…˜์„ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋„๋ก options ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. ์ฟผ๋ฆฌ ์˜ต์…˜์€ React Query์—์„œ ์ œ๊ณตํ•˜๋Š” UseQueryOptions ํƒ€์ž…์„ import ํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. UseQueryOptions, useQuery ๋‘˜์˜ ํƒ€์ž… ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋™์ผํ•˜๋‹ค.

UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>

 

// ์ปค์Šคํ…€ ํ›… ์ •์˜
import { useQuery, UseQueryOptions } from "react-query";
// ...

export default function useClientQuery<T = Client[]>(
  options?: UseQueryOptions<Client[], AxiosError, T>,
) {
  const { getClientList } = ClientAPI;

  return useQuery<Client[], AxiosError, T>(
    queryKeys.CLIENT_LIST,
    getClientList, // resolved data๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฟผ๋ฆฌ ํ•จ์ˆ˜
    options,
  );
}

 

useClientQuery ์ œ๋„ค๋ฆญ ํƒ€์ž… T์˜ ๊ธฐ๋ณธ๊ฐ’์„ Client[]๋กœ ์„ค์ •ํ–ˆ์œผ๋ฏ€๋กœ select ํ•จ์ˆ˜๋ฅผ ๋„˜๊ธฐ์ง€ ์•Š์•˜์„ ๋•Œ data ํƒ€์ž…์€ Client[]๊ฐ€ ๋œ๋‹ค. select ํ•จ์ˆ˜๋ฅผ ๋„˜๊ธฐ๋ฉด select ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’์˜ ํƒ€์ž…์ด data ํƒ€์ž…์ด ๋œ๋‹ค.

 

๐Ÿ’ก select ํ•จ์ˆ˜ ์ธ์ž์—” ์ฟผ๋ฆฌ ํ•จ์ˆ˜์˜ ๋ฆฌํ„ด ๊ฐ’์ด ์ „๋‹ฌ๋œ๋‹ค. ์œ„ ์˜ˆ์‹œ์—์„  Client[] ํƒ€์ž…์˜ data๊ฐ€ ์ „๋‹ฌ๋œ๋‹ค. ์ฐธ๊ณ ๋กœ select ํ•จ์ˆ˜๋Š” ์บ์‹œ์— ์ €์žฅ๋˜๋Š” ๋‚ด์šฉ์—” ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๊ณ , ๋ฐ˜ํ™˜ํ•œ ๋ฐ์ดํ„ฐ ๊ฐ’์—๋งŒ ์˜ํ–ฅ์„ ์ค€๋‹ค.

// ์ปค์Šคํ…€ ํ›… ์‚ฌ์šฉ
// ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ปค์Šคํ…€ ํ›…์„ ์‚ฌ์šฉํ•  ๋•Œ
const selectFn = (data: Client[]) => { /* ... */ };
const { data, ...queryResults } = useClientQuery({ select: selectFn /* ... */ });

 

ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์žˆ์„ ๋•Œ

URL์— ๋™์  path๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜๋Š” API๋ผ๋ฉด(/orders/{userId}) Base Query ํ›…์ด path๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ณ  ์ฟผ๋ฆฌ ํ•จ์ˆ˜๋กœ path๋ฅผ ๋„˜๊ธฐ๋ฉด ๋œ๋‹ค. ์•„๋ž˜ ์˜ˆ์‹œ์—์„  ์ฟผ๋ฆฌ ํ•จ์ˆ˜๊ฐ€ resolved data๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฟผ๋ฆฌ ํ•จ์ˆ˜๋ฅผ async () => (await queryFn(params)).data ํ˜•ํƒœ๋กœ ์ž‘์„ฑํ–ˆ๋‹ค.

// ์ปค์Šคํ…€ ํ›… ์ •์˜
import { useQuery, UseQueryOptions } from "react-query";
// ...

export default function useOrderQuery<T = Order[]>(
  userId: number,
  options?: UseQueryOptions<Order[], AxiosError, T>,
) {
  const { getOrdersById } = OrderAPI;

  return useQuery<Order[], AxiosError, T>(
    queryKeys.ORDER_LIST,
    async () => (await getOrdersById(userId)).data, // resolved data๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฟผ๋ฆฌ ํ•จ์ˆ˜
    options,
  );
}

 

์ฟผ๋ฆฌ ํ•จ์ˆ˜ ๋ฐ˜ํ™˜๊ฐ’ AxiosResponse vs Resolved Data โšก๏ธ

์ฟผ๋ฆฌ ํ•จ์ˆ˜๊ฐ€ AxiosResponse๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์ฟผ๋ฆฌ์˜ TQueryFnData ํƒ€์ž…๋„ ๋™์ผํ•˜๊ฒŒ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค.

//์ฟผ๋ฆฌ ํ•จ์ˆ˜๊ฐ€ AxiosResponse๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ
// AxiosResponse๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฟผ๋ฆฌ ํ•จ์ˆ˜
const getClientList = async () => {
  return await axios.get<Client[]>("clients");
};

// useClientQuery ํ›…
return useQuery<AxiosResponse<Client[]>, AxiosError, T>(/* ... */);

 

์ฟผ๋ฆฌ ํ•จ์ˆ˜๊ฐ€ resolved data๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด TQueryFnData ํƒ€์ž…์— ๋ฐ˜ํ™˜ ๋ฐ์ดํ„ฐ ํƒ€์ž…(Client[])๋งŒ ์ง€์ •ํ•˜๋ฉด ๋œ๋‹ค.

// ์ฟผ๋ฆฌ ํ•จ์ˆ˜๊ฐ€ resolved data๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ
// resolved data๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฟผ๋ฆฌ ํ•จ์ˆ˜
const getClientList = async () => {
  const { data } = await axios.get<Client[]>("clients");
  return data;
};

// useClientQuery ํ›…
return useQuery<Client[], AxiosError, T>(/* ... */);

 

useMutation


์ œ๋„ค๋ฆญ ํƒ€์ž… ํ†บ์•„๋ณด๊ธฐ โšก๏ธ

export function useMutaion<
  TData = unknown,
  TError = unknown,
  TVariables = void,
  TContext = unknown
>

 

โถ TData : mutation ํ•จ์ˆ˜ ์‹คํ–‰ ๊ฒฐ๊ณผ ํƒ€์ž… (AxiosResponse<T> ๋“ฑ)

TData ํƒ€์ž…์€ โถonSuccess ์ฝœ๋ฐฑ์˜ ์ธ์ž ํƒ€์ž…๊ณผ โทuseMutation ํ›…์ด ๋ฐ˜ํ™˜ํ•˜๋Š” data ํƒ€์ž…์ด ๋œ๋‹ค. 

const { data } = useMutation<AxiosResponse<boolean>>(postTodo, {
  onSuccess: (res) => { /* ... */ },
});
// data ํƒ€์ž… : AxiosResponse<boolean> | undefined
// onSuccess ์ฝœ๋ฐฑ์˜ res ์ธ์ž ํƒ€์ž… : AxiosResponse<boolean>

 

โท TError : mutation ํ•จ์ˆ˜ ์—๋Ÿฌ ํƒ€์ž… (AxiosError ๋“ฑ)

TError ํƒ€์ž…์€ โถonError ์ฝœ๋ฐฑ์˜ ์ธ์ž ํƒ€์ž…๊ณผ โทuseMutation ํ›…์ด ๋ฐ˜ํ™˜ํ•˜๋Š” error ํƒ€์ž…์ด ๋œ๋‹ค. 

const { error } = useMutation<AxiosResponse<boolean>, AxiosError>(postTodo, {
  onError: (err) => { /* ... */ },
});
// error ํƒ€์ž… : AxiosError | null
// onError ์ฝœ๋ฐฑ์˜ err ์ธ์ž ํƒ€์ž… : AxiosError

 

โธ TVariables : mutation ํ•จ์ˆ˜์˜ ์ธ์ž ํƒ€์ž…

TVariables ํƒ€์ž…์€ mutate ํ•จ์ˆ˜์™€ onSuccess ๋“ฑ ์˜ต์…˜ ๋ฉ”์„œ๋“œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์ธ์ž ํƒ€์ž…์ด ๋œ๋‹ค. 

const { mutate } = useMutation<AxiosResponse<boolean>, AxiosError, number>(
  postTodo, // mutationFn
  {
    onSuccess: (res, id) => { /* ... */ },
    onError: (err, id) => { /* ... */ },
    onMutate: (id) => { /* ... */ },
    onSettled: (res, err, id) => { /* ... */ },
  },
);

const onClick = () => mutate(8);

 

โน TContext : onMutate ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ๋ฆฌํ„ด ํƒ€์ž…

onMutate ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋Š” mutation ํ•จ์ˆ˜ ์‹คํ–‰ ์ „์— ์‹คํ–‰๋˜๋ฉฐ, onMutate ๊ฒฐ๊ณผ ๊ฐ’์€ onSuccess ๊ฐ™์€ ์˜ต์…˜ ๋ฉ”์„œ๋“œ์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜ ์ธ์ž๋กœ ์ „๋‹ฌ๋œ๋‹ค. 

const { mutate } = useMutation<
  AxiosResponse<boolean>,
  AxiosError,
  number,
  number
>(postTodo, {
  onSuccess: (res, id, nextId) => { /* ... */ },
  onError: (err, id, nextId) => { /* ... */ },
  onMutate: (id) => id + 1, // onMutate ์ฝœ๋ฐฑ ํ•จ์ˆ˜์˜ ์ธ์ž(id) ํƒ€์ž…์€ TVariables
  onSettled: (res, err, id, nextId) => { /* ... */ },
});

// onSuccess, onMutate, onSettled ์ฝœ๋ฐฑ์˜ nextId ์ธ์ž๋Š” onMutate์˜ ๋ฆฌํ„ด๊ฐ’(number)

 

Base Mutation ์ปค์Šคํ…€ ํ›…

Base Query ์ปค์Šคํ…€ ํ›…์„ ์ •์˜ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ํ›…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ณณ์—์„œ mutation ์˜ต์…˜์„ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋„๋ก options ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ UseQueryOptions ํƒ€์ž…์„ importํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.

 

๐Ÿ” invalidateQueries vs setQueryData : invalidation is less code on the frontend, but one more network request. That's the tradeoff (via TanStack Discussions)

  • invalidateQueries : refetch related queries that should be stale after the mutation
  • setQueryData : merge mutation response to current query data

 

mutation ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ ์ดํ›„ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•  ์ž‘์—…์ด ์žˆ๋‹ค๋ฉด onSuccess, onError ๊ฐ™์€ ์˜ต์…˜ ๋ฉ”์„œ๋“œ๋ฅผ ๋ฏธ๋ฆฌ ์ •์˜ํ•ด๋‘˜ ์ˆ˜๋„ ์žˆ๋‹ค. ์ฐธ๊ณ ๋กœ mutation์€ ๋ช…์‹œํ•œ ์ฟผ๋ฆฌํ‚ค๋ฅผ stale ๋ฐ์ดํ„ฐ๋กœ ์ทจ๊ธ‰ํ•˜๋„๋กํ•ด์„œ re-fetching์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” queryClient.invalidateQueries ๋ฉ”์„œ๋“œ์™€ ์ž์ฃผ ์‚ฌ์šฉํ•œ๋‹ค.

// ์ปค์Šคํ…€ ํ›… ์ •์˜
import { useMutation, UseQueryOptions } from "react-query";
// ...

export default function useAddTodoMutation(
  options?: UseMutationOptions<PostTodoResponse, AxiosError, PostTodoPayload>,
) {
  // PostTodoResponse ํƒ€์ž… : AxiosResponse<boolean>
  // PostTodoPayload ํƒ€์ž… : number
  return useMutation<PostTodoResponse, AxiosError, PostTodoPayload>(
    // AxiosResponse๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” mutation ํ•จ์ˆ˜ ↓
    // id ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž…์€ PostTodoPayload ↓
    (id) => postTodo(id),
    options,
  );
}

 

useAddTodoMutation ํ›…์ด ๋ฐ˜ํ™˜ํ•˜๋Š” mutate ํ•จ์ˆ˜๋กœ mutation์„ ์‹คํ–‰์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. mutate ํ•จ์ˆ˜์˜ ์ฒซ๋ฒˆ์งธ ์ธ์ž๋Š” mutation ํ•จ์ˆ˜๋กœ ์ „๋‹ฌ๋˜๋ฉฐ, useMutation 3๋ฒˆ์งธ ์ œ๋„ค๋ฆญ ํƒ€์ž…์œผ๋กœ ๋„˜๊ธด PostTodoPayload ํƒ€์ž…(TVariables)์„ ๊ฐ–๋Š”๋‹ค. ํ•„์š”์— ๋”ฐ๋ผ onSuccess ๊ฐ™์€ ์˜ต์…˜ ๋ฉ”์„œ๋“œ๋ฅผ ๋„˜๊ธธ ์ˆ˜๋„ ์žˆ๋‹ค.

// ์ปค์Šคํ…€ ํ›… ์‚ฌ์šฉ
const onSuccess = () => { /* ... */ };
const { mutate, ...useMutationResults } = useAddTodoMutation({ onSuccess });

const onClick = (id: PostTodoPayload) => mutate(id);
// mutate ํ•จ์ˆ˜ ๋‘๋ฒˆ์งธ ์ธ์ž์— { onError, onSettled, onSuccess }๋ฅผ ๋„˜๊ธธ ์ˆ˜๋„ ์žˆ๋‹ค.
// ex) mutate(id, { onSuccess: () => {} })
// ์‹คํ–‰ ์ˆœ์„œ : useMutation ์˜ต์…˜ ๋ฉ”์„œ๋“œ -> mutate ์˜ต์…˜ ๋ฉ”์„œ๋“œ

 

์ œ๋„ค๋ฆญ์œผ๋กœ ๊น”๋”ํ•˜๊ฒŒ ์ž‘์„ฑํ•˜๊ธฐ โšก๏ธ


useQuery|Mutation์— ์ œ๋„ค๋ฆญ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์ฟผ๋ฆฌ(API) ํ•จ์ˆ˜๋„ ์ œ๋„ค๋ฆญ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ์ˆ˜์ •ํ•ด์•ผ ํ•œ๋‹ค.

const getClientList = async <T = Client[],>() => {
  const { data } = await axios.get<T>("clients");
  return data;
};

 

Query ํ›…์˜ ์ œ๋„ค๋ฆญ T๋Š” ์ฟผ๋ฆฌ ํ•จ์ˆ˜ ๋ฆฌํ„ด ํƒ€์ž…(TQueryFnData)์œผ๋กœ, K๋Š” ์ตœ์ข… ๋ฆฌํ„ด ํƒ€์ž…(TData)์œผ๋กœ ๋“ค์–ด๊ฐ€๋„๋ก ์ˆ˜์ •ํ•œ๋‹ค. T, K ๋ชจ๋‘ ๊ธฐ๋ณธ๊ฐ’์„ ์ง€์ •ํ–ˆ์œผ๋ฏ€๋กœ, ์ง€์ •ํ•œ ํƒ€์ž…๊ณผ ๋™์ผํ•˜๋‹ค๋ฉด ๋”ฐ๋กœ ๋„˜๊ธฐ์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

// useQuery ์ œ๋„ค๋ฆญ ์‚ฌ์šฉ ์˜ˆ์‹œ
export default function useClientQuery<T = Client[], K = T>(
  options?: UseQueryOptions<T, AxiosError, K>,
) {
  const { getClientList } = ClientAPI;

  return useQuery<T, AxiosError, K>(
    queryKeys.CLIENT_LIST,
    getClientList,
    options,
  );
}

 

Mutation ํ›…์˜ ์ œ๋„ค๋ฆญ T๋Š” mutation ํ•จ์ˆ˜ ์‹คํ–‰ ๊ฒฐ๊ณผ ํƒ€์ž…(TData)์œผ๋กœ, K๋Š” mutation ํ•จ์ˆ˜์˜ ์ธ์ž ํƒ€์ž…(TVariables)์œผ๋กœ ๋“ค์–ด๊ฐ€๋„๋ก ์ˆ˜์ •ํ•œ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ฟผ๋ฆฌ ํ•จ์ˆ˜๊ฐ€ ์ œ๋„ค๋ฆญ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

// useMutation ์ œ๋„ค๋ฆญ ์‚ฌ์šฉ ์˜ˆ์‹œ
export default function useAddTodoMutation<
  T = PostTodoResponse,
  K = PostTodoPayload,
>(options?: UseMutationOptions<T, AxiosError, K>) {
  return useMutation<T, AxiosError, K>((id) => postTodo(id), options);
}

 

๋ ˆํผ๋Ÿฐ์Šค


 


๊ธ€ ์ˆ˜์ •์‚ฌํ•ญ์€ ๋…ธ์…˜ ํŽ˜์ด์ง€์— ๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค. ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”
๋ฐ˜์‘ํ˜•