Home react-query
Post
Cancel

react-query

๐Ÿ“Œ react-query

react-query๋Š” ์„œ๋ฒ„์˜ ๊ฐ’์„ ํด๋ผ์ด์–ธํŠธ์— ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜, ์บ์‹ฑ, ๊ฐ’ ์—…๋ฐ์ดํŠธ, ์—๋Ÿฌํ•ธ๋“ค๋ง ๋“ฑ ๋น„๋™๊ธฐ ๊ณผ์ •์„ ๋”์šฑ ํŽธํ•˜๊ฒŒ ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ ์ด์œ 

์„œ๋ฒ„๋กœ ๋ถ€ํ„ฐ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ์—…๋ฐ์ดํŠธ ํ•˜๋Š” ๋กœ์ง์„ store ๋‚ด๋ถ€์— ๊ฐœ๋ฐœํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ณด๋‹ˆ store๋Š” ํด๋ผ์ด์–ธํŠธ state๋ฅผ ์œ ์ง€ํ•ด์•ผํ•˜๋Š”๋ฐ ์–ด๋А ์ˆœ๊ฐ„๋ถ€ํ„ฐ store์— ํด๋ผ์ด์–ธํŠธ ๋ฐ์ดํ„ฐ์™€ ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ๊ฐ€ ๊ณต์กด ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ react-query๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ ์„œ๋ฒ„, ํด๋ผ์ด์–ธํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

react-query ์žฅ์ 

  • ์บ์‹ฑ
  • get์„ ํ•œ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด update๋ฅผ ํ•˜๋ฉด ์ž๋™์œผ๋กœ get์„ ๋‹ค์‹œ ์ˆ˜ํ–‰ํ•œ๋‹ค. (์˜ˆ๋ฅผ ๋“ค๋ฉด ๊ฒŒ์‹œํŒ์˜ ๊ธ€์„ ๊ฐ€์ ธ์™”์„ ๋•Œ ๊ฒŒ์‹œํŒ์˜ ๊ธ€์„ ์ƒ์„ฑํ•˜๋ฉด ๊ฒŒ์‹œํŒ ๊ธ€์„ getํ•˜๋Š” api๋ฅผ ์ž๋™์œผ๋กœ ์‹คํ–‰ )
  • ๋ฐ์ดํ„ฐ๊ฐ€ ์˜ค๋ž˜ ๋˜์—ˆ๋‹ค๊ณ  ํŒ๋‹จ๋˜๋ฉด ๋‹ค์‹œ get (invalidateQueries)
  • ๋™์ผ ๋ฐ์ดํ„ฐ ์—ฌ๋Ÿฌ๋ฒˆ ์š”์ฒญํ•˜๋ฉด ํ•œ๋ฒˆ๋งŒ ์š”์ฒญํ•œ๋‹ค. (์˜ต์…˜์— ๋”ฐ๋ผ ์ค‘๋ณต ํ˜ธ์ถœ ํ—ˆ์šฉ ์‹œ๊ฐ„ ์กฐ์ ˆ ๊ฐ€๋Šฅ)
  • ๋ฌดํ•œ ์Šคํฌ๋กค (Infinite Queries (opens new window))
  • ๋น„๋™๊ธฐ ๊ณผ์ •์„ ์„ ์–ธ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • react hook๊ณผ ์‚ฌ์šฉํ•˜๋Š” ๊ตฌ์กฐ๊ฐ€ ๋น„์Šทํ•˜๋‹ค.

setting

next 13์—์„œ ๊ธฐ๋ณธ layout.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import "./globals.css";
import { QueryClient, QueryClientProvider } from "react-query";
import { ReactQueryDevtools } from "react-query/devtools";

const queryClient = new QueryClient();

export default function RootLayout({
  children,
}: {
  children: React.ReactNode,
}) {
  return (
    <html lang="en">
      {/*
        <head /> will contain the components returned by the nearest parent
        head.tsx. Find out more at https://beta.nextjs.org/docs/api-reference/file-conventions/head
      */}
      <head />
      <body>
        <QueryClientProvider client={queryClient}>
          <ReactQueryDevtools initialIsOpen={true} />
          {children}
        </QueryClientProvider>
      </body>
    </html>
  );
}

useQuery

  • ๋ฐ์ดํ„ฐ๋ฅผ get ํ•˜๊ธฐ ์œ„ํ•œ api์ž…๋‹ˆ๋‹ค. post, update๋Š” useMutation์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ์ฒซ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ unique Key๊ฐ€ ๋“ค์–ด๊ฐ€๊ณ , ๋‘๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋น„๋™๊ธฐ ํ•จ์ˆ˜(apiํ˜ธ์ถœ ํ•จ์ˆ˜)๊ฐ€ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. (๋‹น์—ฐํ•œ ๋ง์ด์ง€๋งŒ ๋‘๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” promise๊ฐ€ ๋“ค์–ด๊ฐ€์•ผํ•ฉ๋‹ˆ๋‹ค.)
  • ์ฒซ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์„ค์ •ํ•œ unique Key๋Š” ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ๋„ ํ•ด๋‹น ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ˜ธ์ถœ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. unique Key๋Š” string๊ณผ ๋ฐฐ์—ด์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. ๋ฐฐ์—ด๋กœ ๋„˜๊ธฐ๋ฉด 0๋ฒˆ ๊ฐ’์€ string๊ฐ’์œผ๋กœ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ถ€๋ฅผ ๊ฐ’์ด ๋“ค์–ด๊ฐ€๊ณ  ๋‘๋ฒˆ์งธ ๊ฐ’์„ ๋„ฃ์œผ๋ฉด query ํ•จ์ˆ˜ ๋‚ด๋ถ€์— ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ํ•ด๋‹น ๊ฐ’์ด ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.
  • return ๊ฐ’์€ api์˜ ์„ฑ๊ณต, ์‹คํŒจ์—ฌ๋ถ€, api return ๊ฐ’์„ ํฌํ•จํ•œ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.
  • useQuery๋Š” ๋น„๋™๊ธฐ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ํ•œ ์ปดํฌ๋„ŒํŠธ์— ์—ฌ๋Ÿฌ๊ฐœ์˜ useQuery๊ฐ€ ์žˆ๋‹ค๋ฉด ํ•˜๋‚˜๊ฐ€ ๋๋‚˜๊ณ  ๋‹ค์Œ useQuery๊ฐ€ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ๋‘๊ฐœ์˜ useQuery๊ฐ€ ๋™์‹œ์— ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋น„๋™๊ธฐ query๊ฐ€ ์žˆ๋‹ค๋ฉด useQuery๋ณด๋‹ค๋Š” ๋ฐ‘์— ์„ค๋ช…ํ•ด ๋“œ๋ฆด useQueries๋ฅผ ๊ถŒ์œ ๋“œ๋ฆฝ๋‹ˆ๋‹ค.
  • enabled๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด useQuery๋ฅผ ๋™๊ธฐ์ ์œผ๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜ ์˜ˆ์‹œ๋กœ ์ถ”๊ฐ€ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

status

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function Todos() {
  const { status, data, error } = useQuery("todos", fetchTodoList);

  if (status === "loading") {
    return <span>Loading...</span>;
  }

  if (status === "error") {
    return <span>Error: {error.message}</span>;
  }

  return (
    <ul>
      {data.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  );
}

status๋กœ loading, error ํ•œ๋ฒˆ์— ์ฒ˜๋ฆฌ๊ฐ€๋Šฅ

useQuery ๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰

1
2
3
4
5
6
7
8
const { data: todoList, error, isFetching } = useQuery("todos", fetchTodoList);
const {
  data: nextTodo,
  error,
  isFetching,
} = useQuery("nextTodos", fetchNextTodoList, {
  enabled: !!todoList, // true๊ฐ€ ๋˜๋ฉด fetchNextTodoList๋ฅผ ์‹คํ–‰ํ•œ๋‹ค
});

useQueries

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const usersQuery = useQuery("users", fetchUsers);
const teamsQuery = useQuery("teams", fetchTeams);
const projectsQuery = useQuery("projects", fetchProjects);

//์œ„์˜ ์ฝ”๋“œ๋ฅผ

//์•„๋ž˜ ์ฒ˜๋Ÿผ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ
const result = useQueries([
  {
    queryKey: ["getRune", riot.version],
    queryFn: () => api.getRunInfo(riot.version),
  },
  {
    queryKey: ["getSpell", riot.version],
    queryFn: () => api.getSpellInfo(riot.version),
  },
]);

useEffect(() => {
  console.log(result); // [{rune ์ •๋ณด, data: [], isSucces: true ...}, {spell ์ •๋ณด, data: [], isSucces: true ...}]
  const loadingFinishAll = result.some((result) => result.isLoading);
  console.log(loadingFinishAll); // loadingFinishAll์ด false์ด๋ฉด ์ตœ์ข… ์™„๋ฃŒ
}, [result]);

useMutation

  • ๊ฐ’์„ ๋ฐ”๊ฟ€๋•Œ ์‚ฌ์šฉํ•˜๋Š” api. return ๊ฐ’์€ useQuery์™€ ๋™์ผ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const riot = {
  version: "12.1.1",
};

const result = useQueries([
  {
    queryKey: ["getRune", riot.version],
    queryFn: (params) => {
      console.log(params); // {queryKey: ['getRune', '12.1.1'], pageParam: undefined, meta: undefined}

      return api.getRunInfo(riot.version);
    },
  },
  {
    queryKey: ["getSpell", riot.version],
    queryFn: () => api.getSpellInfo(riot.version),
  },
]);

updateํ›„์— get ๋‹ค์‹œ ์‹คํ–‰

1
2
3
4
5
6
const mutation = useMutation(postTodo, {
  onSuccess: () => {
    // postTodo๊ฐ€ ์„ฑ๊ณตํ•˜๋ฉด todos๋กœ ๋งตํ•‘๋œ useQuery api ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
    queryClient.invalidateQueries("todos");
  },
});
  • mutation์—์„œ return๋œ ๊ฐ’์„ ์ด์šฉํ•ด์„œ get ํ•จ์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผํ•  ๊ฒฝ์šฐ setQueryData๋ฅผ ์‚ฌ์šฉ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const queryClient = useQueryClient();

const mutation = useMutation(editTodo, {
  onSuccess: (data) => {
    // data๊ฐ€ fetchTodoById๋กœ ๋“ค์–ด๊ฐ„๋‹ค
    queryClient.setQueryData(["todo", { id: 5 }], data);
  },
});

const { status, data, error } = useQuery(["todo", { id: 5 }], fetchTodoById);

mutation.mutate({
  id: 5,
  name: "nkh",
});
This post is licensed under CC BY 4.0 by the author.

JS[iterable, iterator]

NextJS13