react-query 강의 정리
상태 차이
Client State
- 웹 브라우저 세션과 관련된 모든 정보
- ex. 사용자는 가장 잘 아는 언어로 텍스트를 읽기 위해 언어를 선택하거나, 다크모드 선택 등 => 서버에서 일어나는 일과는 관련 없음
- 단순히 사용자의 상태 추적
Server State
- 서버 상태는 서버에 저장된다
- 클라이언트에 표시하는데 필요한 데이터
- ex. 데이터베이스에 저장되는 데이터 (게시글)
React-Query
-
react code에서 서버 데이터가 필요할 때, Fetch, Axios 등을 사용해서 서버로 바로 이동하지 않고 React Query 캐시를 요청
-
역할 : react-query 클라이언트를 어떻게 구성했느냐에 따라 해당 캐시의 데이터를 유지, 관리하는 역할
-
데이터를 관리하는 것은 react-query이지만, 서버의 새 데이터로 캐시를 업데이트하는 시기를 설정하는 것은 사용자 역할
예시
'blog-posts'라는 키가 있는 데이터 => 데이터 식별 방식
- 클라이언트 캐시에 있는 이 데이터가 서버의 데이터와 일치하는지 확인해야 함
- 방법 2가지
1) 명령형 : 쿼리 클라이언트에 이 데이터를 무효화, 캐시에 교체할 새 데이터를 서버에서 가지고 오게 명령
2) 선언형 : 리패치를 트리거(유발)하는 조건 구성 => 브라우저 창이 다시 포커스 되었을 때 => staleTime으로 다시 가져오는 것도 조절 할 수 있음
(30초 후 브라우저 창이 다시 포커싱 되었을 때 서버에서 새 데이터를 가져오게)
- react-query에는 상태 관리를 위한 툴이 제공 된다
1) 서버에 대한 모든 쿼리의 로딩 / 오류 상태를 유지 => 수동 작업 x
2) 페이지네이션, 무한스크롤에 필요한 데이터 및 도구 제공
3) 사용자가 필요한 시점을 예상해서 프리패치를 제공
: 데이터를 미리 가져와서 캐시에 넣어놓고 사용자가 필요할 때 제공 (서버 연결을 기다릴 필요가 없다)
4) 서버에서 데이터 변이나 업데이트를 관리할 수 있음
5) 쿼리는 키로 식별되기 때문에 react-query는 요청을 관리 할 수 있고, 페이지를 로드하고 해당 페이지의 여러 구성 요소가 동일한 데이터를 요청하는 경우 쿼리를 한 번에 보낼 수 있음
: 기존 쿼리가 나가는 동안 다른 구성 요소가 데이터를 요청하는 경우 중복 요청을 제거 할 수 있음
6) 서버에서 오류가 발생하는 경우에 대한 재시도 관리
7) 쿼리가 성공, 오류 났을 때를 구별해서 조치를 취할 수 있도록 콜백 전달
react-query ver.3 설치하기
npm install react-query@^3
React Query 버전 4를 사용하시는 경우, 다음과 같은 특이사항이 있다.
-
버전 4에서는 설치와 임포트(import)에 react-query가 아닌 @tanstack/react-query를 사용하시는 것을 권장
-
쿼리 키는 반드시 배열이어야 하며, 만약 강의에서 문자열을 쿼리 키로 사용하는 경우, 해당 문자열을 반드시 배열 안에 넣어야 함
-
onSuccess는 더 이상 setQueryData에서 호출되지 않는다.
이전과는 달리 setQueryData를 호출한 이후에 onSuccess를 호출하는 것으로 작동 순서를 바꾸었기 때문에, 이 상황에서 학습 내용을 버전 4에 적용하시면 문제가 발생
첫번째 프로젝트에서 배울 것
Getting Started
- npm install react-query
- Create query client
- 쿼리와 서버의 데이터 캐시를 관리하는 클라이언트
- Apply QueryProvider
- 자녀 컴포넌트에 캐시와 클라이언트 구성을 제공할 QueryProvider 적용
- 이에 대한 값으로 사용 될 쿼리 클라이언트 필요
- Run useQuery
Apply QueryProvider
기존
queryclient와 queryclientprovider를 적용한다.
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<div className="App">
<h1>Blog Posts</h1>
<Posts />
</div>
</QueryClientProvider>
);
}
이 쿼리 클라이언트가 있어야, 공급자를 추가 할 수 있게 되고
공급자가 이 클라이언트가 가지고 있는 캐시, 옵션등을 자녀 컴포넌트로 보낼 수 있다.
이제 내부 posts 컴포넌트에서도 react-query와 관련된 hook을 사용할 수 있게 된다.
하드 코딩 된 data가 아닌 useQuery를 활용하여 데이터를 가져오게 된다.
useQuery와 함께 사용해야 할 몇 가지 인수
1) 쿼리 키 = 쿼리 이름
2) 쿼리 함수 = 쿼리에 대한 데이터를 가져오는 방식 (fetchBoards, fetchPosts = 비동기 함수)
컴포넌트 상단에 쿼리 함수
async function fetchPosts() {
const response = await fetch(
'https://~~~~~~~~~'
);
return response.json();
}
우리가 매핑 할 데이터는 fetchPosts 에서 반환 된 데이터가 되고 => 위 HTTP 요청에서 반환 된 JSON
=> 비동기 함수이기 때문에, map 실행이 안 될 것.
=> 지금은 if(!data)로 임시방편을 해두자.
데이터가 정의되지 않았을 때 오류로 두지 않고 처리하는 방법은?
isLoading / isError
isLoading 데이터가 로딩중인지 여부
isError 데이터를 가져올 때 오류여부
-
로딩하는 동안은 loading....가 보인다
-
에러가 나면... Oops..가 보인다.
=> 리액트 쿼리는 기본값으로 3번 시도한 이후에 오류를 결정한다. (바꿀 수 있음!)
=> 시도하는 중간에는 loading.. 3번 이후에 오류
-
반환 객체에는 쿼리 함수에서 전달하는 error도 있어서, 활용할 수 있다.
isLoading과 isFetching의 차이점?
isFetching
- 비동기 쿼리가 해결되지 않았음
- 페칭을 완료하지 않았다는 의미
- 쿼리가 axios 호출, 또는 graphql 호출일 수 있다.
isLoading
- 이에 대한 하위 집합
- 가져오고 있는 상태, 쿼리 함수가 해결되지 않았음
- 캐시 된 데이터도 없음 (표시할 캐시 데이터도 없음)
- 이 쿼리를 만든 적이 없다.
=> 페이지네이션을 진행할 때 캐시된 데이터가 있을 때와 없을 때를 구분해야 하기 때문에 알아야 함
- 쿼리 키로 쿼리 표시
- 활성, 비활성, 만료 등의 모든 쿼리 상태를 알려줌
- 업데이트 된 타임스태프 확인
- 쿼리에 의해 반환된 데이터를 탐색할 수 있음
- 쿼리를 볼 수 있는 쿼리 탐색 가능
- 개발 중에만 표시, 프로덕션에는 표시되지 않음
데브 툴을 설치하고, app.jsx
와!
꽃이 생겼다.
내가 불러온 posts 라는 쿼리와 그 내용들, 불러온 시간 등등등의 정보를 볼 수 있다!
Stale Data
stale Data
- 만료된 데이터
- 데이터 리패칭은 만료된 데이터에서만 실행된다.
- 데이터 리패칭 실행에는 만료된 데이터 외의 다양한 트리거가 있다.
ex) 컴포넌트가 다시 마운트 될 때, 윈도우가 다시 포커스 되었을 때
- 데이터를 허용하는 '최대 나이'
- 데이터가 만료되었다고 판단하기 전까지 허용하는 시간 Stale Time
- 웹 사이트에 표시된 데이터가 10초까지 괜찮다? => Stale Time = 10초 (데이터의 성격마다 다름)
- 업데이트 하는 방법
useQuery 호출 시, 세 번째 인수 추가하기 (options)
왜 기본값이 0일까? => 데이터는 항상 만료상태이므로, 서버에서 다시 가져와야 한다고 가정하는 것
=> 실수로 클라이언트에게 만료될 데이터를 제공할 가능성이 줄어든다!
stale Time vs cacheTime
- 캐시는 나중에 다시 필요할 수도 있는 데이터
- 특정 쿼리에 대한 활성 useQuery가 없는 경우, 해당 데이터는 콜드 스토리지로 이동
- 구성된 cacheTime이 지나면 캐시 데이터가 만료되며 (유효시간 5분)
- catchTime이 관찰하는 시간의 양은 특정 쿼리에 대한 useQuery가 활성화 된 후 경과한 시간
- 페이지에 표시되는 컴포넌트가 특정 쿼리에 대해 useQuery를 사용한 시간
- 캐시가 만료되면 가비지 컬렉션이 실행되고, 클라이언트는 사용 불가
- 데이터가 캐시에 있는 동안에는 패칭할때 사용 가능
- 데이터 패칭을 중지하지 않으므로 서버의 최신 데이터로 새로고침이 가능
- 하지만 계속해서 빈페이지만 보는 경우 생길 수 있음 => 무슨 데이터인지?
- 새로운 데이터를 수집하는 동안 약간 오래된 데이터를 표시하는 편이 빈페이지 보다 낫다
- 만료된 데이터가 위험한 경우에는 cacheTime을 0으로