일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 정규표현식
- 카드뉴스
- 웹접근성
- TypeScript
- react-query
- leetcode
- 제로베이스 프론트엔드 스쿨
- 디자인
- react
- html&css
- JavaScript
- 프로그래머스
- programmers
- wai-aria
- 비트연산자
- 알고리즘
- Today
- Total
記錄
React-Query 본문
React-query?
- 기존의 Redux, Recoil 등의 전역 상태관리 라이브러리를 사용하여 비동기 데이터를 처리하는 방식은 client state를 처리하는 데는 효과적이나 server state를 처리하는데는 효과적이지 못함
- 프로젝트 크기가 커질수록 api 호출 후 전역 상태를 업데이트해줘야 하는 상황마다 작성해야 하는 코드가 많아지고, 비동기 데이터 처리 로직으로 인해 store가 과도하게 비대해지는 문제점이 있음
1.api 호출 후 응답 데이터 > server state
2.ui 개발 위한 데이터(theme 등) > client state
=> 전역상태관리 라이브러리가 본연의 역할인 전역으로 관리해야 할 데이터(Global State)를 관리하는 데 집중할 수 있도록 Server 데이터와 Client 데이터를 분리시켜줌
React Query의 특징
- Caching 지원.
- 동일한 데이터에 대한 중복 요청을 제거하고 한 번만 요청하도록 함.
- "out of date" 상태의 데이터를 파악하고 updating 지원.
- Pagination 및 Lazy Loading 성능 최적화.
- Server State의 메모리 관리 및 garbage collection 지원.
- React Hooks와 유사한 인터페이스 제공.
staleTime, cacheTime 개념
staleTime
- 신선하지 않은 데이터 = stale(상한 상태)
- 실제 서버에서 갖고 있는 데이터와 클라이언트가 갖고 있는 데이터가 서로 일치하지 않을 가능성이 존재하는 데이터
- 브라우저나 특정 Element에 포커스가 맞춰지면 API를 호출하거나, 일정 시간이 지난 뒤에는 데이터가 상했을 것이라 추측하고 다시 요청하는 등 다양한 방법을 이용해서 데이터를 갱신
- 데이터 fetch(fresh 상태) => staleTime(기본값 0) 이후 stale 상태로 변경
- 데이터가 한번 fetch 되고 나서 staleTime이 지나지 않았다면 unmount 후 mount 되어도 fetch가 일어나지 않음
cacheTime : 데이터가 inactive 상태일 때 캐싱된 상태로 남아있는 시간
- unmount되면 데이터는 inactive상태로 변경되고, 일정 시간 지나면 캐시를 삭제함
(staleTime infinity로 설정해도 상관없이 삭제되고, 무조건 inactive된 시점 기준으로 cacheTime만큼 유지됨)
=> useQuery로 패치한 결과를 캐시해두고 있는데, 이걸 신선하지 않다고 보기 때문에 refetch할 수 있음
설치
$ npm i react-query
$ yarn add react-query
//react query v4 부터는 tanstack query 로 라이브러리명이 변경
$ npm i @tanstack/react-query
$ yarn add @tanstack/react-query
main.tsx 설정
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { QueryClient, QueryClientProvider } from "react-query";
import "./index.css";
//클라이언트 생성
const queryClient = new QueryClient();
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<React.StrictMode>
//비동기 요청 처리 위한 Context Provider -> QueryClientProvider로 감싸서 사용
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
</React.StrictMode>
);
React Query 사용법
useQuery
- 서버에서 데이터를 가져오기(get) 위해 사용하는 hook
- refetching, caching, 전역 사용 위해 유니크한 key(Query Key) 필요
- 중복된 API 호출을 Query Key를 이용하여 구분하고 중복되는 요청에 대해서는 캐시에 저장해 둔 데이터를 활용하여 네트워크 요청을 최소화
- 데이터 사용할 때 필요한 중요한 상태들을 보유하고 있음
isLoading | status === 'loading' | 쿼리 로딩 상태(캐싱된 데이터 없을 때 fetch 중에 true) |
isSuccess | status === 'success' | 쿼리 사용 가능 상태 |
isIdle | status === 'idle' | 쿼리를 사용할 수 없는 상태(disabled) |
isError | status === 'error' | 쿼리에 에러가 발생한 상태 |
error | 쿼리가 isError 상태인 경우 에러 정보 확인을 위해 사용하는 프로퍼티 | |
data | 쿼리가 isSucess 상태인 경우 데이터 사용을 위해 사용하는 프로퍼티 | |
isFetching | 쿼리의 fetching/refetching 여부에 대한 boolean 값 (데이터가 fetch될 때 true, 캐싱 데이터 이어서 백그라운드에서 fetch 되더라도 true) |
//사용 예시
const fetchData = async () => {
const res = await axios.get('https://62debc799c47ff309e7aeb36.mockapi.io/api/tempuser');
return res.data;
}
const queryfetch = useQuery(
['temp_query'], //queryKey: 유니크한 키값
// tanstack query의 경우 key값 하나여도 배열로 선언해야 함(업데이트)
fetchData, //queryFunction(queryFn): 비동기 API 함수, promise를 반환
{
//options : 쿼리에 사용할 옵션값
})
function Todos() {
const { isLoading, isError, data, error } = useQuery('todos', fetchTodoList)
if (isLoading) {
return <span>Loading...</span>
}
if (isError) {
return <span>Error: {error.message}</span>
}
// `isSuccess === true`
return (
<ul>
{data.map(todo => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
)
}
useQueries
- useQuery는 기본적으로 비동기로 동작하기 때문에 컴포넌트 내에 여러 개의 useQuery가 있을 경우 동시에 실행됨
- useQueries 사용하면 여러 개의 쿼리를 하나로 묶어서 사용할 수 있음
- 쿼리 옵션 객체들의 배열을 받고 배열의 형태로 반환
function App({ users }) {
const userQueries = useQueries(
users.map(user => {
return {
queryKey: ['user', user.id],
queryFn: () => fetchUserById(user.id),
}
})
)
}
Mutation
- 전역적으로 사용됨(Create, Update, Delete data)
- useMutation hook 사용
function App(){
const mutation = useMutation(newTodo => {
return axios.post('/todos', newTodo)
})
return (
<div>
{mutation.isLoading ? (Adding todo...) : (
<>
{mutation.isError ? (
<div>An error occurred: {mutation.error.message} </div>
) : null}
{mutation.isSuccess ? <div>Todo added!</div>: null}
<button onClick={()=>{mutation.mutate({id:new Date(), title: 'Do Laundry'})}}>
Create Todo
</button>
</>
)}
</div>
)
}
Query Invalidation
- invalidateQueries를 사용해 쿼리 무효화
- 쿼리를 stale하다고 마크해두고 잠재적으로 refetch
queryClient.invalidateQueries() //아무 인자 남기지 않으면 캐시된 모든 쿼리에 대해 invalidate 처리
queryClient.invalidateQueries('todos') //문자열을 가지고 시작하는 값들에 대해 invalidate 처리
default 설정하기
import { QueryClient } form 'react-query'
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: Infinity,
}
}
})
참고자료
https://tech.osci.kr/2022/07/13/react-query/
https://www.dgmunit1.com/blog/setting/next-tanstack-query#_apptsx-%EC%84%A4%EC%A0%95
https://freestrokes.tistory.com/170
'FRONTEND STUDY > React' 카테고리의 다른 글
JSON-SERVER (0) | 2023.02.20 |
---|---|
[React 스터디] SPA, Routing (0) | 2023.01.09 |
[React 스터디 - 6] 리액트 CSS 적용 방법 (0) | 2022.12.25 |
[React 스터디-5] List, Key (0) | 2022.12.18 |
[React Study - 5] Life cycle, useEffect() (0) | 2022.12.11 |