Skip to content

Latest commit

ย 

History

History
413 lines (307 loc) ยท 13.9 KB

File metadata and controls

413 lines (307 loc) ยท 13.9 KB

๐Ÿ’ป queryOptions & mutationOptions ์ฃผ์š” ๋‚ด์šฉ

  • queryOptions์™€ mutationOptions๋Š” ์ฟผ๋ฆฌ/๋ฎคํ…Œ์ด์…˜ ์˜ต์…˜์„ ํ•œ๊ณณ์— ๋ชจ์•„ ๋‘๊ณ , ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ํƒ€์ž… ์•ˆ์ „ํ•˜๊ฒŒ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ํ—ฌํผ์ž…๋‹ˆ๋‹ค.
  • ๋Ÿฐํƒ€์ž„์—์„œ๋Š” ์ธ์ž๋กœ ๋ฐ›์€ ๊ฐ์ฒด๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•ญ๋“ฑ ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ์ถ”๊ฐ€์ ์ธ ๋Ÿฐํƒ€์ž„ ๋น„์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์˜จ์ „ํžˆ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋ฅผ ์œ„ํ•œ ํ—ฌํผ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
  • ์ง€์› ๋ฒ„์ „์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
    • queryOptions, infiniteQueryOptions: v5.0.0๋ถ€ํ„ฐ
    • mutationOptions: v5.82.0๋ถ€ํ„ฐ

๐Ÿ“ƒ ๋ชฉ์ฐจ

  1. queryOptions๊ฐ€ ํ•„์š”ํ•œ ์ด์œ 
  2. queryOptions ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•
  3. queryOptions์™€ ํ•จ๊ป˜ ์“ฐ๋Š” API
  4. ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„ ์˜ต์…˜ ์žฌ์ •์˜
  5. ํƒ€์ž…์ด ๋ถ™์€ queryKey(DataTag)
  6. initialData์™€ skipToken ์˜ค๋ฒ„๋กœ๋“œ
  7. Query Key Factory ํŒจํ„ด
  8. infiniteQueryOptions
  9. mutationOptions
  10. mutationOptions ์‚ฌ์šฉ ์‹œ ์ฃผ์˜ํ•  ์ 
  11. ์ •๋ฆฌ

queryOptions๊ฐ€ ํ•„์š”ํ•œ ์ด์œ 

  • useQuery์— ์˜ต์…˜์„ ์ธ๋ผ์ธ์œผ๋กœ ์ž‘์„ฑํ•˜๋ฉด ํƒ€์ž… ์ถ”๋ก ์ด ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ์žฌ์‚ฌ์šฉํ•˜๋ ค๊ณ  ์˜ต์…˜์„ ๋ณ„๋„ ํ•จ์ˆ˜๋กœ ๋ถ„๋ฆฌํ•˜๋Š” ์ˆœ๊ฐ„, queryKey๊ฐ€ ๋“ค๊ณ  ์žˆ๋˜ ๋ฐ์ดํ„ฐ ํƒ€์ž… ์ •๋ณด๊ฐ€ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.
// โŒ ์ผ๋ฐ˜ ๊ฐ์ฒด๋กœ ๋ถ„๋ฆฌํ•œ ๊ฒฝ์šฐ
const groupOptions = (id: number) => ({
  queryKey: ["groups", id],
  queryFn: () => fetchGroups(id),
  staleTime: 5 * 1000,
});

// useQuery์˜ data๋Š” ์ถ”๋ก ๋˜์ง€๋งŒ,
const { data } = useQuery(groupOptions(1));

// ๋ช…๋ นํ˜• API์—์„œ๋Š” queryKey์— ํƒ€์ž… ์ •๋ณด๊ฐ€ ์—†์–ด unknown์ด ๋ฉ๋‹ˆ๋‹ค.
const groups = queryClient.getQueryData(groupOptions(1).queryKey);
//    ^? unknown
  • queryOptions๋กœ ๊ฐ์‹ธ๋ฉด ๋ฐ˜ํ™˜๋œ queryKey๊ฐ€ queryFn์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์„ ํ•จ๊ป˜ ๋“ค๊ณ  ๋‹ค๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋ช…๋ นํ˜• API์—์„œ๋„ ์ œ๋„ค๋ฆญ์„ ๋งค๋ฒˆ ๋ช…์‹œํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
// โœ… queryOptions๋กœ ๊ฐ์‹ผ ๊ฒฝ์šฐ
const groups = queryClient.getQueryData(groupOptions(1).queryKey);
//    ^? Group[] | undefined

queryOptions ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

  • queryOptions์—๋Š” useQuery์— ๋„˜๊ธธ ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์„ ๊ทธ๋Œ€๋กœ ๋„˜๊ธธ ์ˆ˜ ์žˆ์œผ๋ฉฐ, queryKey๋Š” ํ•„์ˆ˜๊ฐ’์ž…๋‹ˆ๋‹ค.
import { queryOptions } from "@tanstack/react-query";

export const groupOptions = (id: number) =>
  queryOptions({
    queryKey: ["groups", id],
    queryFn: () => fetchGroups(id),
    staleTime: 5 * 1000,
    // ...options
  });
  • ์ธ์ž๊ฐ€ ํ•„์š” ์—†๋‹ค๋ฉด ํ•จ์ˆ˜๋กœ ๊ฐ์‹ธ์ง€ ์•Š๊ณ  ์ƒ์ˆ˜๋กœ ์„ ์–ธํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค.
export const groupsOptions = queryOptions({
  queryKey: ["groups"],
  queryFn: fetchGroups,
});

queryOptions์™€ ํ•จ๊ป˜ ์“ฐ๋Š” API

  • queryOptions๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ๊ฐ์ฒด๋Š” ์ฟผ๋ฆฌ ์˜ต์…˜์„ ๋ฐ›๋Š” ๋Œ€๋ถ€๋ถ„์˜ ํ›…๊ณผ queryClient ๋ฉ”์„œ๋“œ์— ๊ทธ๋Œ€๋กœ ๋„˜๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
// ํ›…
useQuery(groupOptions(1));
useSuspenseQuery(groupOptions(1));
useQueries({
  queries: [groupOptions(1), groupOptions(2)],
});

// queryClient ๋ฉ”์„œ๋“œ
queryClient.prefetchQuery(groupOptions(1));
queryClient.fetchQuery(groupOptions(1));
queryClient.ensureQueryData(groupOptions(1));
  • queryKey๋งŒ ํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ์—๋Š” .queryKey๋ฅผ ๊บผ๋‚ด์„œ ๋„˜๊ฒจ์ค๋‹ˆ๋‹ค.
queryClient.setQueryData(groupOptions(1).queryKey, newGroups);
queryClient.invalidateQueries({ queryKey: groupOptions(1).queryKey });
queryClient.cancelQueries({ queryKey: groupOptions(1).queryKey });

์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„ ์˜ต์…˜ ์žฌ์ •์˜

  • ๊ณตํ†ต ์˜ต์…˜์€ ๊ทธ๋Œ€๋กœ ๋‘๊ณ , ์ปดํฌ๋„ŒํŠธ์—์„œ ํ•„์š”ํ•œ ์˜ต์…˜๋งŒ ๋ฎ์–ด์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ€ํ‘œ์ ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ๋งˆ๋‹ค ๋‹ค๋ฅธ select ํ•จ์ˆ˜๋ฅผ ๋ถ™์ด๋Š” ํŒจํ„ด์ด ์žˆ์Šต๋‹ˆ๋‹ค.
const { data } = useQuery({
  ...groupOptions(1),
  select: (data) => data.map((group) => group.name),
});

/**
 * ํƒ€์ž… ์ถ”๋ก ์ด ์œ ์ง€๋˜๋ฏ€๋กœ data๋Š” select์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์ด ๋ฉ๋‹ˆ๋‹ค.
 * data: string[] | undefined
 */

ํƒ€์ž…์ด ๋ถ™์€ queryKey(DataTag)

  • queryOptions๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” queryKey์—๋Š” DataTag๋ผ๋Š” ํƒ€์ž… ์ •๋ณด๊ฐ€ ํ•จ๊ป˜ ๋ถ™์Šต๋‹ˆ๋‹ค. ๋•๋ถ„์— queryClient์˜ ๋ช…๋ นํ˜• API์—์„œ ์ œ๋„ค๋ฆญ ์—†์ด๋„ ํƒ€์ž…์ด ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค.
// โœ… ์ œ๋„ค๋ฆญ์„ ๋ช…์‹œํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.
const groups = queryClient.getQueryData(groupsOptions.queryKey);
//    ^? Group[] | undefined

// โŒ ์ง์ ‘ ๋ฐฐ์—ด์„ ๋„˜๊ธฐ๋ฉด ๋งค๋ฒˆ ์ œ๋„ค๋ฆญ์„ ๋ช…์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
const groups2 = queryClient.getQueryData<Group[]>(["groups"]);
  • setQueryData์˜ updater ํ•จ์ˆ˜๋„ ์ด์ „ ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์ถ”๋ก ํ•ฉ๋‹ˆ๋‹ค.
queryClient.setQueryData(groupsOptions.queryKey, (oldData) => {
  // oldData: Group[] | undefined
  return oldData ? [...oldData, newGroup] : oldData;
});
  • ๐Ÿ’ก ๋‹จ, getQueriesData๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ํƒ€์ž…์˜ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํƒ€์ž… ์ถ”๋ก ์ด ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋•Œ๋Š” ์ œ๋„ค๋ฆญ์„ ์ง์ ‘ ๋ช…์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
const entries = queryClient.getQueriesData<Group[]>({
  queryKey: groupsOptions.queryKey,
});
//    ^? Array<[QueryKey, Group[] | undefined]>

initialData์™€ skipToken ์˜ค๋ฒ„๋กœ๋“œ

1. initialData

  • initialData๋ฅผ ํ•จ๊ป˜ ๋„˜๊ธฐ๋ฉด data๊ฐ€ undefined๊ฐ€ ๋˜์ง€ ์•Š๋Š” ์˜ค๋ฒ„๋กœ๋“œ๊ฐ€ ์„ ํƒ๋ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์ปดํฌ๋„ŒํŠธ์—์„œ data๋ฅผ ์˜ต์…”๋„ ์ฒด์ด๋‹ ์—†์ด ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
export const postsOptions = queryOptions({
  queryKey: ["posts"],
  queryFn: fetchPosts,
  initialData: [],
});

function Posts() {
  const { data, isError, error } = useQuery(postsOptions);

  return (
    <div>
      {isError ? <span>Error: {error.message}</span> : null}
      <ul>
        {/* data: Post[] (undefined๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค) */}
        {data.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
}

2. skipToken

  • ํŠน์ • ์กฐ๊ฑด์—์„œ๋งŒ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค๋ฉด queryFn์— skipToken์„ ๋„˜๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. enabled: false์™€ ๋น„์Šทํ•˜๊ฒŒ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š์ง€๋งŒ, queryFn์˜ ์ธ์ž๊ฐ€ undefined์ผ ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์„ ํƒ€์ž… ๋ ˆ๋ฒจ์—์„œ ์•ˆ์ „ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
import { queryOptions, skipToken, useQuery } from "@tanstack/react-query";

export const postOptions = (postId: number | undefined) =>
  queryOptions({
    queryKey: ["post", postId],
    queryFn: postId != null ? () => fetchPost(postId) : skipToken,
  });

function Post({ postId }: { postId: number | undefined }) {
  const { data, isLoading, isError, error } = useQuery(postOptions(postId));

  if (postId == null) return "Select a post";
  if (isLoading) return "Loading...";
  if (isError) return <span>Error: {error.message}</span>;

  return <h1>{data?.title}</h1>;
}

Query Key Factory ํŒจํ„ด

  • queryOptions๋ฅผ ๋ชจ์•„ ๋‘๋ฉด ๋ณ„๋„์˜ query key factory ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—†์ด๋„ ๋„๋ฉ”์ธ๋ณ„ ์ฟผ๋ฆฌ๋ฅผ ํ•œ๊ณณ์—์„œ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
import { queryOptions } from "@tanstack/react-query";

export const postQueries = {
  all: () =>
    queryOptions({
      queryKey: ["posts"],
      queryFn: fetchPosts,
    }),
  detail: (id: number) =>
    queryOptions({
      queryKey: ["posts", id],
      queryFn: () => fetchPost(id),
      staleTime: 60 * 1000,
    }),
};
// ์‚ฌ์šฉ ์˜ˆ์‹œ
useQuery(postQueries.detail(1));
queryClient.prefetchQuery(postQueries.detail(2));

// ["posts"]๋ฅผ ํฌํ•จํ•˜๋Š” ๋ชจ๋“  ์ฟผ๋ฆฌ๊ฐ€ ๋ฌดํšจํ™”๋ฉ๋‹ˆ๋‹ค.
queryClient.invalidateQueries({ queryKey: postQueries.all().queryKey });

infiniteQueryOptions

  • ๋ฌดํ•œ ์ฟผ๋ฆฌ์—๋Š” infiniteQueryOptions๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ๋ฒ•์€ queryOptions์™€ ๋™์ผํ•˜๋ฉฐ, initialPageParam๊ณผ getNextPageParam์„ ํ•จ๊ป˜ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
import { infiniteQueryOptions, useInfiniteQuery } from "@tanstack/react-query";

export const colorsOptions = () =>
  infiniteQueryOptions({
    queryKey: ["colors"],
    queryFn: ({ pageParam }) => fetchColors(pageParam),
    initialPageParam: 1,
    getNextPageParam: (lastPage, allPages) => {
      return allPages.length < 4 ? allPages.length + 1 : undefined;
    },
  });

const { data, fetchNextPage, hasNextPage } = useInfiniteQuery(colorsOptions());

mutationOptions

  • v5.82.0๋ถ€ํ„ฐ ๋ฎคํ…Œ์ด์…˜์—๋„ ๋™์ผํ•œ ํ—ฌํผ์ธ mutationOptions๊ฐ€ ์ถ”๊ฐ€๋์Šต๋‹ˆ๋‹ค. useMutation์— ๋„˜๊ธธ ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์„ ๊ทธ๋Œ€๋กœ ๋„˜๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • queryOptions์™€ ๋‹ฌ๋ฆฌ ์ถ”๊ฐ€์ ์ธ ํƒ€์ž… ์ •๋ณด๋ฅผ ๋ถ™์ด์ง€ ์•Š๊ณ  ๋ฐ›์€ ๊ฐ์ฒด๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์˜ต์…˜ ๊ฐ์ฒด์— ๋Œ€ํ•œ ํƒ€์ž… ๊ฒ€์‚ฌ์™€ ์ž๋™ ์™„์„ฑ์„ ๋ฐ›๊ธฐ ์œ„ํ•œ ํ—ฌํผ์ž…๋‹ˆ๋‹ค.

1. mutationKey๊ฐ€ ์—†๋Š” ํ˜•ํƒœ

  • useMutationState๋‚˜ ํ•„ํ„ฐ๋กœ ๋ฎคํ…Œ์ด์…˜์„ ์ฐพ์•„ ์“ธ ์ผ์ด ์—†๋‹ค๋ฉด mutationKey๋ฅผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
import { mutationOptions, useMutation } from "@tanstack/react-query";

export const createPostOptions = mutationOptions({
  mutationFn: createPost,
});

function CreatePost() {
  const { mutate } = useMutation(createPostOptions);

  return <button onClick={() => mutate({ title: "Hello" })}>Create</button>;
}

2. mutationKey๊ฐ€ ์žˆ๋Š” ํ˜•ํƒœ

  • mutationKey๋ฅผ ์ง€์ •ํ•˜๋ฉด ๋‚˜์ค‘์— useMutationState, useIsMutating ๋“ฑ์œผ๋กœ ํ•ด๋‹น ๋ฎคํ…Œ์ด์…˜์˜ ์ƒํƒœ๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
import { mutationOptions, useMutationState } from "@tanstack/react-query";

export const createPostOptions = mutationOptions({
  mutationKey: ["posts", "create"],
  mutationFn: createPost,
});

// ์ „์—ญ "์ €์žฅ ์ค‘..." ์ธ๋””์ผ€์ดํ„ฐ
function SavingIndicator() {
  const isCreatingPost =
    useMutationState({
      filters: {
        mutationKey: createPostOptions.mutationKey,
        status: "pending",
      },
    }).length > 0;

  return isCreatingPost ? <span>Savingโ€ฆ</span> : null;
}
  • ์˜ต์…˜ ๊ฐ์ฒด ์ž์ฒด๋ฅผ ํ•„ํ„ฐ๋กœ ๋„˜๊ธธ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
useIsMutating(createPostOptions);
queryClient.isMutating(createPostOptions);

mutationOptions ์‚ฌ์šฉ ์‹œ ์ฃผ์˜ํ•  ์ 

  • mutationOptions๋Š” ๊ฐ์ฒด๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์Šคํ”„๋ ˆ๋“œ๋กœ ์ฝœ๋ฐฑ์„ ๋ง๋ถ™์ด๋ฉด ์›๋ณธ ์ฝœ๋ฐฑ์ด ๋ฎ์–ด์จ์ง‘๋‹ˆ๋‹ค.
export const createPostOptions = mutationOptions({
  mutationFn: createPost,
  onSuccess: () => console.log("A"),
});

useMutation({
  ...createPostOptions,
  onSuccess: () => console.log("B"), // โŒ "A"๋Š” ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
});
  • ์›๋ณธ ์ฝœ๋ฐฑ์„ ํ•จ๊ป˜ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ง์ ‘ ํ˜ธ์ถœํ•ด ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.
useMutation({
  ...createPostOptions,
  onSuccess: (data, variables, context) => {
    createPostOptions.onSuccess?.(data, variables, context);
    console.log("B");
  },
});
  • ๐Ÿ’ก ๋” ๊ถŒ์žฅ๋˜๋Š” ๋ฐฉ๋ฒ•์€ ๊ณตํ†ต ๋กœ์ง๊ณผ ์ปดํฌ๋„ŒํŠธ ์ „์šฉ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
    • ์ฟผ๋ฆฌ ๋ฌดํšจํ™”์ฒ˜๋Ÿผ ํ•ญ์ƒ ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ๋กœ์ง์€ mutationOptions(= useMutation)์˜ Callback์— ๋‘ก๋‹ˆ๋‹ค.
    • ๋ฆฌ๋‹ค์ด๋ ‰์…˜์ด๋‚˜ ํ† ์ŠคํŠธ์ฒ˜๋Ÿผ ํ™”๋ฉด๋งˆ๋‹ค ๋‹ค๋ฅธ ๋กœ์ง์€ mutate์˜ Callback์œผ๋กœ ๋„˜๊น๋‹ˆ๋‹ค.
    • ์ž์„ธํ•œ ๋‚ด์šฉ์€ useMutation callback๊ณผ mutate callback์˜ ์ฐจ์ด๋ฅผ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”.
export const createPostOptions = mutationOptions({
  mutationFn: createPost,
  onSuccess: () => {
    // ๊ณตํ†ต ๋กœ์ง
    queryClient.invalidateQueries({ queryKey: postQueries.all().queryKey });
  },
});

const { mutate } = useMutation(createPostOptions);

mutate(newPost, {
  // ์ปดํฌ๋„ŒํŠธ ์ „์šฉ ๋กœ์ง
  onSuccess: () => navigate("/posts"),
});

์ •๋ฆฌ

queryOptions mutationOptions
์ง€์› ๋ฒ„์ „ v5.0.0 v5.82.0
ํ•„์ˆ˜ ์˜ต์…˜ queryKey ์—†์Œ(์˜ค๋ฒ„๋กœ๋“œ์— ๋”ฐ๋ผ mutationKey)
๋ฐ˜ํ™˜ ๊ฐ’ ์˜ต์…˜ ๊ฐ์ฒด + ํƒ€์ž…์ด ๋ถ™์€ queryKey(DataTag) ๋ฐ›์€ ์˜ต์…˜ ๊ฐ์ฒด ๊ทธ๋Œ€๋กœ
์ฃผ์š” ์‚ฌ์šฉ์ฒ˜ useQuery, useSuspenseQuery, useQueries, queryClient.* useMutation, useMutationState, useIsMutating
๋Ÿฐํƒ€์ž„ ๋™์ž‘ ์ธ์ž๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ ์ธ์ž๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜
  • ๋‘ ํ—ฌํผ ๋ชจ๋‘ ๋Ÿฐํƒ€์ž„ ๋™์ž‘์€ ์—†๊ณ  ํƒ€์ž… ์ถ”๋ก ๊ณผ ์˜ต์…˜ ์žฌ์‚ฌ์šฉ์„ ์œ„ํ•ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.
  • ์˜ต์…˜์„ ๋ณ„๋„ ํŒŒ์ผ๋กœ ๋ถ„๋ฆฌํ•ด ์žฌ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด ๋„์ž… ๋น„์šฉ์ด ๊ฑฐ์˜ ์—†์œผ๋ฏ€๋กœ ์ ๊ทน์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ƒ ์ฐธ๊ณ  ๋ฌธ์„œ