๐ 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",
});
|