-
728x90
원래는 React Query였으나 v4부터 Tanstack Query로 변경되었다고 함!
1. React Query(Tanstack Query)란?
React Query는 서버에서 데이터 가져오기, 캐싱, 동기화, 업데이트 하는 것을 쉽게 만들어주는 라이브러리
일반적으로 사용하는 Redux, MobX와 같은 상태관리 라이브러리는 주로 클라이언트 상태에 초점을 맞추고 있는데
React Query는 서버 상태를 관리하여 서버에서 가져오거나, 업데이트 해야하는 데이터에 초점을 두며 클라이언트 상태 뿐 아니라 서버 상태도 효율적으로 관리할 수 있도록 도와준다.
*클라이언트 상태(Client State)는 주로 UI와 관련된 상태, 서버 상태(Server State)는 DB에 저장되는 데이터
2. React Query 시작하기
npm i @tanstack/react-query yarn add @tanstack/react-query
세팅을 하기 위해 React의 최상위에 React Query가 전체에서 사용할 수 있도록 QueryClientProvider를 제공해야한다.
// main.tsx import {QueryClient, QueryClientProvider} from "@tanstack/react-query"; // Create a client const queryClient = new QueryClient() ReactDOM.createRoot(document.getElementById('root')!).render( <React.StrictMode> {/* Provide the client to your App */} <QueryClientProvider client={queryClient}> <App/> </QueryClientProvider> </React.StrictMode>, )
이렇게 작성해놓고 서버쪽에서 데이터를 요청해야하는데 연습이기때문에 서버를 구축하는 것보다
json-server를 설치해서 API를 만들고 데이터를 json 형식으로 생성하도록 했다.
npm i -g json-server yarn global add json-server
json 데이터 파일을 만든 후 npx json-server src/api/data.json 로 서버를 실행시킬 수 있다.
3. useQuery
const PostList = () => { const {data: postData, isLoading, isError, error, status} = useQuery({ queryKey: ["posts"], queryFn: fetchPosts }) }
useQuery훅을 사용해서 데이터를 비동기적으로 가져올 수 있는데
옵션으로 queryKey는 데이터를 식별할 수 있도록 하는 고유한 키.
두번째 queryFn은 데이터를 요청하는 데 사용되는 비동기 함수 또는 API를 가져오는 내부 쿼리 함수를 지정한다. (promise를 반환하는 함수)
그리고 useQuery 훅이 반환하는 객체의 속성이 정말 많지만, 그중에서 data는 가져온 데이터.
status는 현재 쿼리의 상태 (pending, error, success 중 하나)
isLoading은 status를 기반으로 한 boolean 값으로 데이터를 가져오는 중인지 여부
isError는 status를 기반으로 한 boolean값으로 데이터를 가져오는 도중 오류가 발생했는지 여부
error는 에러 객체로 에러가 발생하지 않은 경우 기본값으로 null 할당
데이터가 정의되기 전 로딩은 true, 데이터를 받자마자 로딩이 false로 바뀌는데
데이터를 가져오는 동안 로딩 상태를 간단히 처리할 수 있어 useState 훅으로 일일이 로딩 상태를 관리하는 것보다 편리하다.
https://tanstack.com/query/v4/docs/framework/react/reference/useQuery
4. useMutation
useQuery로 데이터를 불러올 수 있었다면, POST, PATCH, PUT, DELETE와 같이 데이터를 변경하기 위해 useMutation을 사용한다.
const {mutate, isError: isPostError, isPending, error: postError, reset} = useMutation({ mutationFn: addPost, }) const handleSubmit = (e) => { e.preventDefault(); mutate({id: postData.length + 1, title, tags}) e.target.reset(); }
useMutation훅을 사용해서 글을 추가하는 작업을 처리하려고 한다.
아까와 마찬가지로 mutationFn는 비동기 함수로 promise를 반환해야한다.
이것 또한 반환하는 객체의 속성이 많지만, mutate는 데이터를 수정하고 업데이트하는 데 사용되는 함수로 이 함수를 호출하면 지정된 mutationFn 함수가 실행된다.
isError는 현재 mutation 작업이 에러로 끝났는지 여부를 나타내는 boolean 값 (에러는 true)
isPending은 mutation 작업이 진행중인지 여부를 나타내는 boolean 값 (진행중이면 true)
error는 mutation 작업 중 발생한 에러를 나타내는 객체 (에러 발생 X null)
reset은 mutation 작업을 초기 상태로 재설정하는 함수
mutation 함수를 호출해서 전달할 데이터를 객체 형태로 전달,
그리고 e.target.reset() 으로 입력했던 폼을 비우도록 설정했다.
https://tanstack.com/query/v5/docs/framework/react/reference/useMutation
하지만, 이렇게만 설정하면 작업이 비동기적으로 진행되기 때문에 화면에 바로 업데이트되지 않는다.
데이터가 변경되었으면 이와 관련된 쿼리를 무효화해서 새로운 데이터를 가져올 수 있으며 이를 통해 사용자가 추가한 게시글이 즉시 화면에 표시될 수 있다.
5. Query Invalidation
쿼리 무효화는 어떤 작업을 수행 후 쿼리의 데이터가 더 이상 최신 상태가 아니게 될 때 해당 쿼리를 즉시 무효화하며
예를 들어 게시글을 작성하거나 삭제할 때 화면에 실시간으로 최신화하기 위해 사용할 수 있다.
const queryClient = useQueryClient() const {mutate, isError: isPostError, isPending, error: postError, reset} = useMutation({ mutationFn: addPost, onMutate: () => { return {id: 1} }, onSuccess: (data, variables, context) => { queryClient.invalidateQueries({ queryKey: ['posts'], exact: true, }) } })
이 코드는 useMutation 훅을 사용해서 글을 추가할 때 작업이 성공하면 해당 글이 포함된 쿼리를 무효화하는 기능을 구현했다.
useQueryClient로 쿼리의 상태를 추적해서 새로운 데이터가 필요할 때 자동으로 요청하고 업데이트 한다.onMute는 mutation이 시작되기 전 실행되는 함수로 이 경우 id를 1로 하여 추가한 글을 맨 위에 보여질 수 있도록 했다.
onSuccess는 mutaion이 성공했을 때 실행되는 함수로 이 함수에서 queryClient.invalidateQueries를 사용해서
posts 쿼리를 무효화 시킨다.
exact 옵션은 정확하게 일치하는 쿼리만 다시 가져올 것임을 나타내며
이렇게 하면 해당 쿼리를 다시 실행해서 최신 게시글 목록을 가져올 수 있다.
* queryClient.invalidateQueries(): 모든 쿼리 무효화
* queryClient.invalidateQueries({ queryKey: ['']}): 특정 쿼리 무효화
https://tanstack.com/query/v4/docs/framework/react/guides/query-invalidation
'React, Next' 카테고리의 다른 글
[React] React Hook Form 라이브러리 사용하기 (0) 2024.03.16 [React] 리액트 생명주기 (Life Cycle) (0) 2024.03.03 [React] Virtual DOM 이해하기 (0) 2024.02.27 [React] React로 카카오맵 API 사용하기 (0) 2024.01.27 [React] 올바른 초기값 설정하기 (0) 2024.01.17 댓글