react-query 란
React 애플리케이션에서 데이터를 관리하고 API 호출을 처리할 수 있는 라이브러리이다.
사용하기 쉽고 강력한 기능을 제공해서 데이터 상태를 유지하고 캐싱하여 성능을 최적화할 수 있다.
설치
npm install @tanstack/react-query
셋팅
react query 를 사용하려면 애플리케이션 최상위 파이리에서 QueryClientProvider 를 사용해서 QueryClient 를 제공해야한다.
index.js
import { QueryClient, QueryClientProvider } from "react-query" //1번
const queryClient = new QueryClient() //2번
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<QueryClientProvider client={queryClient}> //3번
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
</QueryClientProvider>
);
react-query 로 ajax 요청하기
useQuery 를 사용해서 API 를 호출하고 데이터를 가져올 수 있다.
useQuery 란 react-query 가 자동으로 데이터를 캐싱하고 관리하는 hook 이다.
import { useQuery } from "react-query";
function App() {
...
//서버에서 사용자 이름 가져오기(자동 refetch)
let username = useQuery("username", () => {
return (
axios.get("https://codingapple1.github.io/userdata.json").then((a) => {
return a.data;
}),
{ staleTime: 2000 }
); //refetch 간격 2초 설정
});
return (
...
서버에서 data를 받아와서 리턴하도록 코드를 짜봤다.
장점으로는
ajax 요청 성공/실패/로딩중 상태를 쉽게 파악할 수 있다.
...
<Nav className="me-auto">
<Nav.Link>
{username.isLoading
? "loading..."
: "환영합니다, " + username.data.name + "님 !"}
</Nav.Link>
</Nav>
...
위처럼 username의 isLoading 값이 true 일 경우에는 "loading..." 이라는 문자열이 뜨도록 했다.
변수.isLoading
변수.error
변수.data
이런식으로 사용이 가능하다.
두번째 장점, ajax 재요청을 자동으로 해준다.
그 페이지에 일정시간동안 있거나
다른 페이지 갔다가 오거나, 이런 경우들에 알아서 ajax 요청을 다시 해준다.
staleTime 으로 재요청 간격을 조정해줄 수 있다.
세번째 장점, 실패하면 재시도를 자동으로 해준다.
네번째 장점, ajax 로 가져온 결과는 state 공유할 필요가 없다.
무슨 말이냐면 내가 지금은 App 컴포넌트에서 ajax 요청으로 데이터를 가져오고 있지만
Detail 컴포넌트에서 이 데이터가 필요하다고 해서 props 전송을 할 필요가 없다는 말이다.
Detail 컴포넌트에 ajax 요청하는 코드 똑같이 또 적으면 된다.
ajax 요청이 두개더라도 캐싱기능이 있어서 react-query 는 1번만 해준다.
useMutation 으로 데이터 수정
useMutation 을 사용하면 API 를 호출해서 데이터를 수정할 수 있다.
useMutation 은 데이터를 변경하는 함수와 함께 사용한다.
import { useMutation } from 'react-query';
function MyComponent() {
const updateTodoMutation = useMutation((updatedTodo) => {
return fetch(`/api/todos/${updatedTodo.id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(updatedTodo),
});
});
const handleUpdateTodo = (todoId, newTitle) => {
updateTodoMutation.mutate({ id: todoId, title: newTitle });
};
return (
<div>
{/* Your component UI */}
</div>
);
}
결론
react-query 는 DB 를 front 에서 실시간 동기화 하는걸 도와준다.
하지만 꼭 실시간 데이터를 가져와야 하는 사이트가 아니라면
ajax 요청을 계속 날리고, 가져오는 거니까 비효율적일 수도 있다는 점을 기억해야한다.
실시간 데이터를 위한 다른 방식 : 웹소켓, Server-sent events
다른 라이브러리 : RTK Query
Redux Toolkit 설치하면 기본적으로 사용가능.
원래 ajax 요청 후 redux state 변경하고싶으면 컴포넌트 안에서 해야한다(redux state 변경함수 안에서는 ajax 요청 x)
ajax 요청하는 코드를 Slice 안에서 편하게 관리할 수 있도록 해준다고 한다.