useQuery({ queryKey, queryFn, ...options });
const { data, isPending, isError, error } = useQuery({
queryKey: [QUERY_KEY], // 식별자
queryFn: QUERY_FUNCTION // HTTP 요청 함수 (Promise를 반환하는 함수)
});
import { useQueryClient } from "@tanstack/react-query";
const CachedUsers = () => {
const queryClient = useQueryClient();
// 캐싱된 데이터 가져오기
const cachedUsers = queryClient.getQueryData(["users"]);
if (!cachedUsers) return <p>No cached data available.</p>;
return (
<ul>
{cachedUsers.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
};
getQueryData는 React Query의 캐싱 데이터를 반환합니다. 데이터가 없으면 undefined를 반환합니다.
서버에 요청하지 않으므로 빠르게 데이터를 접근할 수 있습니다.
캐싱된 데이터를 수동으로 갱신하려면 queryClient.setQueryData를 사용합니다.
예제: 데이터 갱신
const updateCachedUsers = () => {
const queryClient = useQueryClient();
queryClient.setQueryData(["users"], (oldData) => {
if (!oldData) return [];
return [...oldData, { id: 3, name: "New User" }];
});
};
캐싱된 데이터를 무효화하려면 queryClient.invalidateQueries를 사용합니다.
const invalidateUsers = () => {
const queryClient = useQueryClient();
queryClient.invalidateQueries(["users"]); // 캐싱된 데이터를 무효화하고 다시 요청
};
queryClient.getQueryData를 사용해 데이터를 확인하고, 데이터가 없을 경우 서버 요청으로 데이터를 가져오도록 처리합니다.
const UsersWithFallback = () => {
const queryClient = useQueryClient();
const cachedUsers = queryClient.getQueryData(["users"]);
const { data } = useQuery(["users"], fetchUsers, {
enabled: !cachedUsers, // 캐싱된 데이터가 없을 때만 fetchUsers 호출
initialData: cachedUsers, // 캐싱된 데이터를 초기값으로 설정
});
return (
<ul>
{data.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
};
enabled: 쿼리 실행 조건을 설정. 캐싱된 데이터가 없을 때만 실행.
initialData: 초기 데이터를 설정. 캐싱된 데이터를 초기값으로 제공.
const useTradeDetail = (trade_connect_key) => {
return useQuery(['getTradeDetail', trade_connect_key], () => fetchTradeDetail(trade_connect_key), {
enabled: false, // 초기화 시 자동 호출 방지
});
};
const { data, isLoading, isError, refetch } = useTradeDetail(tradeKey);
const handleFetch = () => {
refetch(); // 수동으로 데이터 호출
};
React Query는 두 번째 인자인 Query Function을 호출할 때, queryKey 전체를 인자로 전달합니다.
const fetchTradeDetail = async ({ queryKey }) => {
const [_, trade_connect_key] = queryKey; // queryKey에서 값 추출
const response = await fetch(`/api/trade/${trade_connect_key}`);
return response.json();
};
서버 데이터를 변경하는 요청을 처리하며, 일반적으로 POST, PUT, DELETE 요청에 사용됩니다.
React Query의 캐싱과 쿼리 무효화를 활용해 데이터 동기화를 자동화할 수 있습니다.
onSuccess, onError, onSettled
onMutate: 변이가 실행되기 직전에 호출됩니다. 낙관적 업데이트(Optimistic Update)에 사용됩니다.
onSuccess: 변이가 성공적으로 완료된 후 실행됩니다.
onSuccess 콜백은 세 개의 인자를 받습니다
data: 서버로부터 응답받은 response
variables: 요청 시 전달한 파라미터 (즉, onMutate에서 사용했던 newData와 동일)
context: onMutate에서 반환한 값
onError: 변이 도중 에러가 발생했을 때 실행됩니다.
onSettled: 성공/실패 여부와 관계없이 항상 실행됩니다.
const mutation = useMutation(addUser, {
onMutate: async (newUser) => {
await queryClient.cancelQueries(["users"]);
const previousUsers = queryClient.getQueryData(["users"]);
queryClient.setQueryData(["users"], (old) => [...old, newUser]);
return { previousUsers };
},
onError: (err, newUser, context) => {
queryClient.setQueryData(["users"], context.previousUsers);
},
onSuccess: (data, variables, context) => {
queryClient.invalidateQueries(["users"]);
},
onSettled: () => {
queryClient.invalidateQueries(["users"]);
},
});
1) 낙관적 업데이트
데이터를 서버에 요청하기 전에 UI를 미리 업데이트하여 사용자 경험을 개선합니다.
onMutate: (newUser) => {
const previousUsers = queryClient.getQueryData(["users"]);
queryClient.setQueryData(["users"], (old) => [...old, newUser]);
return { previousUsers };
},
핵심: 무효화와 자동 리패칭의 과정!