원문 보기 : https://tkdodo.eu/blog/react-query-as-a-state-manager
TL;DR
리액트 쿼리는 데이터 페치 라이브러리가 아니라, 상태관리 라이브러리 입니다.
비동기 상태 관리 도구
React Query는 비동기 상태 관리자입니다.
Promise를 리턴하는 한, 모든 형태의 비동기 상태를 관리할 수 있습니다.
QueryKey를 통해 해당 상태를 식별하며, 데이터 페칭을 추상화합니다.
export const useTodos = () => useQuery(['todos'], fetchTodos)
function ComponentOne() {
const { data } = useTodos()
}
function ComponentTwo() {
// ✅ will get exactly the same data as ComponentOne
const { data } = useTodos()
}
const queryClient = new QueryClient()
function App() {
return (
<QueryClientProvider client={queryClient}>
<ComponentOne />
<ComponentTwo />
</QueryClientProvider>
)
}
데이터 동기화 도구
데이터를 가져온 후에도 여전히 정확합니까?
React Query는 뷰를 실제 데이터 소유자인 백엔드와 동기화하는 수단을 제공합니다.
이제 에러는 너무 자주 업데이트해서가 아니라, 충분히 자주 업데이트하지 않아 발생합니다.
리액트 쿼리 이전
fetch once, distribute globally, rarely update
fetch on every mount, keep it local
Stale While Revalidate
데이터가 없다는 것은 일반적으로 로딩 스피너를 의미하고
이것은 사용자에게 "느린" 것으로 인식되기 때문에
오래된 데이터가 데이터가 없는 것보다 낫다는 것입니다.
Smart refetches
캐시 무효화는 꽤 어렵습니다.
그렇다면 백엔드에 새 데이터를 다시 요청할 때라고 결정하는 시점은 언제입니까?
확실히 useQuery를 호출하는 컴포넌트가 다시 렌더링될 때마다 이 작업을 수행할 수는 없습니다.
그것은 현대 기준으로도 엄청나게 비쌀 것입니다.
refetchOnMount
refetchOnWindowFocus
개발 중에 브라우저 탭을 매우 자주 전환하므로 리페치가 "너무 많다"고 인식할 수 있습니다만,
프로덕션에서는 탭에서 앱을 열어 두었던 사용자가 이제 메일을 확인하거나 트위터를 읽고 다시 돌아왔음을 나타냅니다.
이 상황에서 그들에게 최신 업데이트를 보여주는 것은 완벽합니다.
refetchOnReconnect
마지막으로 앱 개발자가 적절한 시점을 알고 있다면 queryClient.invalidateQueries를 통해 수동 무효화를 호출할 수 있습니다.
이것은 mutation을 수행한 후에 매우 편리합니다.
Letting React Query do its magic
function ComponentOne() {
const { data } = useTodos()
if (data) {
// ⚠️ mounts conditionally, only after we already have data
return <ComponentTwo />
}
return <Loading />
}
function ComponentTwo() {
// ⚠️ will thus trigger a second network request
const { data } = useTodos()
}
const queryClient = new QueryClient()
function App() {
return (
<QueryClientProvider client={queryClient}>
<ComponentOne />
</QueryClientProvider>
)
}
2초 전에 데이터를 가져왔습니다. 다른 네트워크 요청이 발생하는 이유는 무엇인가요?
— React Query를 처음 사용할 때 정상적인 반응
- props를 통해 데이터를 전달하거나,
- props drilling을 피하기 위해 React 컨텍스트에 넣거나
- refetchOnMount / refetchOnWindowFocus 플래그를 끄는 것이 좋습니다.
function ComponentOne() {
const { data } = useTodos()
const [showMore, toggleShowMore] = React.useReducer(
(value) => !value,
false
)
// yes, I leave out error handling, this is "just" an example
if (!data) {
return <Loading />
}
return (
<div>
Todo count: {data.length}
<button onClick={toggleShowMore}>Show More</button>
// ✅ show ComponentTwo after the button has been clicked
{showMore ? <ComponentTwo /> : null}
</div>
)
}
Customize staleTime
해결책은 staleTime을 특정 사용 사례에 대해 편안한 값으로 설정하는 것입니다. 알아야 할 핵심 사항은 다음과 같습니다.
데이터가 최신 상태인 한 항상 캐시에서만 가져옵니다.
즉 데이터를 몇번이고 리액트 쿼리에서 가져와도, 네트워크 요청을 하지 않습니다.
Bonus: using setQueryDefaults
const queryClient = new QueryClient({
defaultOptions: {
queries: {
// ✅ globally default to 20 seconds
staleTime: 1000 * 20,
},
},
})
// 🚀 everything todo-related will have a 1 minute staleTime
queryClient.setQueryDefaults(todoKeys.all, { staleTime: 1000 * 60 })
관심사의 분리에 대한 노트
요점
- 사용 사례에 이해가 되는 경우에만 다시 가져오기 플래그를 끄고,
- 서버 데이터를 다른 상태 관리자와 동기화하려는 충동을 억제하십시오.
일반적으로 staleTime을 커스터마이징하는 것이
백그라운드 업데이트가 발생하는 빈도를 제어하는 동시에 훌륭한 ux를 얻는 데 필요한 전부입니다.
참고
'FrontEnd' 카테고리의 다른 글
리액트 쿼리 : 네트워크 오프라인 시 동작 (2) | 2022.06.20 |
---|---|
리액트 쿼리 : 에러 처리 (0) | 2022.06.20 |
리액트 쿼리 : 초기값과 플레이스홀더 (0) | 2022.06.19 |
리액트 쿼리 : Query Function Context로 queryFn 타이핑 (0) | 2022.06.19 |
리액트 쿼리 : 쿼리키 (0) | 2022.06.19 |