React 애플리케이션에서 데이터를 가져오기 위한 라이브러리입니다.
데이터 Fetching, 캐싱, 동기화, 서버 쪽 데이터 업데이트 비동기 과정에서 데이터를 관리하기 편하게 할 수 있습니다.
아래와 같이 React는 데이터를 가져올 때 useEffect를 사용하고 useState를 사용하여 상태를 유지합니다.
import React, { useEffect, useState } from "react";
import axios from "axios";
const App = function () {
const [sate, setState] = useState([]);
const load = async () => {
const { data } = await axios.get("http://localhost:4000/api");
setState(data);
};
useEffect(() => {
load();
}, []);
return <div></div>;
};
만약 앱 전체에 데이터가 필요한 경우 상태 관리 라이브러리(Redux, Recoil 등)를 사용하게 됩니다.
기존에 다양한 상태 관리 라이브러리 들은 비동기적 작업보다는 동기적인 클라이언트 데이터를 관리하기에 더 적합하기 때문에
react-query를 사용함으로 서버와 클라이언트 데이터를 분리합니다.
npm i react-query
react-query를 사용할 수 있도록 세팅합니다.
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import { HomePage } from "./components/Home.page";
import { QueryClient, QueryClientProvider } from "react-query";
import { ReactQueryDevtools } from "react-query/devtools";
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<Router>
<Routes>
<Route path="/" element={<HomePage />} />
</Routes>
</div>
</Router>
<ReactQueryDevtools initialIsOpen={false} position={'bottom-right'}/>
</QueryClientProvider>
);
}
export default App;
import { useQuery } from "react-query";
import axios from "axios";
const Page = () => {
const fetch = () => {
return axios.get("http://localhost:4000/api");
};
const { isLoading, data, isError, error } = useQuery(
"key",
fetch,
);
if (isLoading) {
return <h2>Loading...</h2>;
}
if (isError) {
return <h2>{error.message}</h2>;
}
return (
<>
<h2>Hello world</h2>
{data?.data.map((el) => {
return <div key={el.id}>{el.name}</div>;
})}
</>
);
};
import React, { useState } from "react";
import { useQuery } from "react-query";
import axios from "axios";
const App = function () {
const [id, setId] = useState(1);
const load = async () => {
const resp = await axios.get(`http://localhost:4000/${id}`);
return resp;
};
const { data, status } = useQuery(["key", id], load);
...
};
세 번째 인자로 옵션을 설정할 수 있습니다.
const { data, status, isLoading, isFetching } = useQuery(
["key", currentPage],
load,
{
refetchOnWindowFocus: false,
statleTime: 10000,
cashTime: 20000,
}
);
useQuery("names", fetch, {
onSuccess: (data) => {
console.log(data);
},
onError,
select: (data) => {
const names = data.data.map((el) => el.name);
return names;
},
});
useQuery(
"key",
fetchSuperHeroes,
{
initialData: () => {
return {
data: [
{
id: 2,
name: "test",
},
],
};
},
}
);
const { refetch } = useQuery("key", fetch, {
enabled: false,
});
const { isLoading, isError, error, data, isFetching } = useQuery(
["colors", pageNumber],
() => fetchColors(pageNumber),
{
keepPreviousData: true,
}
);
무한 스크롤 또는 더보기와 같은 목록을 로드할 때 유용합니다.
const {
isLoading,
isError,
error,
data,
fetchNextPage,
hasNextPage,
isFetching,
isFetchingNextPage,
} = useInfiniteQuery(["colors"], fetchColors, {
getNextPageParam: (_lastPage, pages) => {
if (pages.length < 4) {
return pages.length + 1;
} else {
return undefined;
}
},
});
useQueriy를 Promise.all처럼 사용할 수 있는 것이 useQueries입니다.
useQueries([
{
queryKey: ["id", id],
queryFn: () => loadIDData(),
},
{
queryKey: ["gender", gender],
queryFn: () => loadGenderData(),
},
]);
쿼리에 대해 성공 및 실패 전처리를 할 수 있습니다.
const queryClient = new QueryClient({
queryCache: new QueryCache({
onError: (error, query) => {
console.log(error, query);
},
onSuccess: (data) => {
console.log(data);
},
}),
});
데이터를 생성, 업데이트 또는 삭제할 때 사용하기 유용합니다.
// Access the client
const queryClient = useQueryClient();
// Queries
const query = useQuery(["todos"], getTodos);
// Mutations
const mutation = useMutation(postTodo, {
onSuccess: () => {
// Invalidate and refetch
queryClient.invalidateQueries(["todos"]);
},
});