๋ฐ˜์‘ํ˜•

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๋Š” ์ฟผ๋ฆฌ ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ์›๋ณธ ๋ฐ์ดํ„ฐ ํƒ€์ž…์ด๊ณ , TData๋Š” ์ตœ์ข…์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ฒŒ ๋  ๋ฐ์ดํ„ฐ ํƒ€์ž…์ด๋‹ค. select ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ์ฟผ๋ฆฌ ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๊ณตํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, TData๋Š” TQueryFnData์™€ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๋‹ค. — 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 ์ธ์ž์—” ํ•ญ์ƒ ๋ฐฐ์—ด๋กœ ์ „๋‹ฌ๋œ๋‹ค. ์ฆ‰, ์ฟผ๋ฆฌํ‚ค๋ฅผ ๋ฌธ์ž์—ด๋กœ ์ง€์ •ํ•ด๋„ ์ฟผ๋ฆฌ ํ•จ์ˆ˜์—” ํ•ญ์ƒ ๋ฐฐ์—ด๋กœ ์ „๋‹ฌ๋˜๋Š” ๊ฒƒ. ์˜ˆ: '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๋Š” ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ์ฒ˜๋ฆฌํ•  ์ฝ”๋“œ๊ฐ€ ์ ์€ ๋Œ€์‹ , ์ฟผ๋ฆฌ๋ฅผ ๋‹ค์‹œ ๊ฐ€์ ธ์˜ค๊ธฐ ๋•Œ๋ฌธ์— ๋„คํŠธ์›Œํฌ ์š”์ฒญ์ด ํ•œ ๋ฒˆ ๋” ๋ฐœ์ƒํ•œ๋‹ค. ๋ฐ˜๋Œ€๋กœ setQueryData๋Š” ์ถ”๊ฐ€ ์š”์ฒญ ์—†์ด ์บ์‹œ๋ฅผ ์ง์ ‘ ๊ฐฑ์‹ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ํ˜„์žฌ ์บ์‹œ์— ๋งž๊ฒŒ ์ง์ ‘ ๋ฐ˜์˜ํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค. (์ฐธ๊ณ  ๋งํฌ)

 

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);
}

 

 

๋ ˆํผ๋Ÿฐ์Šค


๋ฐ˜์‘ํ˜•