-
Notifications
You must be signed in to change notification settings - Fork 0
[Step2.3] cactus: TanStack Query 적용하기 #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: cactus-adv-2.2
Are you sure you want to change the base?
Changes from all commits
6e1ac43
50dc8c2
7ead065
8b920e9
f1714fa
99080d5
47f75be
815e57e
8674c36
a8712bd
4d34d4e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [배움] 한 가지 더 알면 좋을 패턴인데, 프로젝트가 커질수록 Query Key Factory를 많이 쓴다고 합니다. export const restaurantKeys = {
all: () => ["restaurants"],
detail: (id) => ["restaurants", id],
};지금처럼 배열 상수로 두면 나중에 상세 페이지나 필터 조건이 생겼을 때 key 간의 계층 관계를 표현하기 어려운데, Factory 패턴은 restaurantKeys.all()을 invalidate하면 하위 key(detail 등)가 전부 무효화되는 장점이 있어요. 지금 규모에선 오버엔지니어링일 수 있지만, 최종 프로젝트에 적용해보면 좋을 것 같습니다! |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export const RESTAURANTS_QUERY_KEY = ["restaurants"]; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,16 @@ | ||
| import React from "react"; | ||
| import ReactDOM from "react-dom/client"; | ||
| import App from "./App.jsx"; | ||
| import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; | ||
| import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; | ||
|
|
||
| const queryClient = new QueryClient(); | ||
|
|
||
| ReactDOM.createRoot(document.getElementById("root")).render( | ||
| <React.StrictMode> | ||
| <App /> | ||
| <QueryClientProvider client={queryClient}> | ||
| <App /> | ||
| <ReactQueryDevtools initialIsOpen={false} /> | ||
| </QueryClientProvider> | ||
| </React.StrictMode>, | ||
| ); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import { useMutation, useQueryClient } from "@tanstack/react-query"; | ||
| import { addRestaurant } from "../api"; | ||
| import { RESTAURANTS_QUERY_KEY } from "../constants/queryKeys"; | ||
|
|
||
| export function useAddRestaurantMutation() { | ||
| const queryClient = useQueryClient(); | ||
|
|
||
| return useMutation({ | ||
| mutationFn: addRestaurant, | ||
| onMutate: async (newRestaurant) => { | ||
| await queryClient.cancelQueries({ queryKey: RESTAURANTS_QUERY_KEY }); | ||
| const previous = queryClient.getQueryData(RESTAURANTS_QUERY_KEY); | ||
| const optimisticItem = { | ||
| id: `optimistic-${Date.now()}`, | ||
| ...newRestaurant, | ||
| }; | ||
| queryClient.setQueryData(RESTAURANTS_QUERY_KEY, (old) => { | ||
| const current = Array.isArray(old) ? old : []; | ||
| return [...current, optimisticItem]; | ||
| }); | ||
| return { previous }; | ||
| }, | ||
| onError: (err, _, context) => { | ||
| if (context?.previous) { | ||
| queryClient.setQueryData(RESTAURANTS_QUERY_KEY, context.previous); | ||
| } | ||
| }, | ||
| onSettled: () => { | ||
| queryClient.invalidateQueries({ queryKey: RESTAURANTS_QUERY_KEY }); | ||
| }, | ||
| }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import { useQuery } from "@tanstack/react-query"; | ||
| import { getRestaurants } from "../api"; | ||
| import { RESTAURANTS_QUERY_KEY } from "../constants/queryKeys"; | ||
|
|
||
| export function useRestaurantsQuery() { | ||
| return useQuery({ | ||
| queryKey: RESTAURANTS_QUERY_KEY, | ||
| queryFn: getRestaurants, | ||
| }); | ||
| } |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[배움]
early return 방식을 하면 early return 이후 newRestaurants가 반드시 존재한다는 게 보장돼서 제 코드에서
restaurants ?? []같은 방어 코드가 필요 없어진다는 점에서 인상적입니다.