비동기 처리를
쉽게 관리할 수 있는 라이브러리Client state
에 적합한 라이브러리fresh
요청이 만료되지 않은 쿼리
새롭게 추가된 쿼리
최신 상태의 쿼리
fetching
stale
inactive
데이터를 갱신
해야 함.어떤 시점
에 데이터를 refetching
하는지 알 수 있는 옵션
을 제공함.refetchOnWindowFocus
: 브라우저에 포커스가 들어온 경우refetchOnMount
: 새로운 컴포넌트 마운트가 발생한 경우refetchOnReconnect
: 네트워크 재연결이 발생한 경우staleTime
cacheTime
fetch 하는 동안만
! 캐싱된 데이터를 임시로
보여주는 것!⇒ 사용자가 특정 이벤트
가 발생했을 때 refetching
하도록 설정할 수 있음!
Client Data
Sever Data
const { data, isLoading } = useQueries(
['unique-key'],
() => {
return api({
url: URL,
method: 'GET',
});
},
{
onSuccess: (data) => {
// data로 이것저것 하는 로직
}
},
{
onError: (error) => {
// error로 이것저것 하는 로직
}
}
)
💡 기본적으로
GET - useQuery
/PUT, UPDATE, DELETE - useMutation
사용
// useQuery 활용 코드
const { isLoading, error, data } = useQuery({
queryKey: ['repoData'],
queryFn: () =>
fetch('https://api.github.com/repos/tannerlinsley/react-query').then(
(res) => res.json(),
),
})
// 전체 예시 코드
import {
QueryClient,
QueryClientProvider,
useQuery,
} from '@tanstack/react-query'
const queryClient = new QueryClient()
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Example />
</QueryClientProvider>
)
}
function Example() {
// data를 통해, fetch 성공 시 데이터 반환 가능
const { isLoading, error, data } = useQuery({
queryKey: ['repoData'],
queryFn: () =>
fetch('https://api.github.com/repos/tannerlinsley/react-query').then(
(res) => res.json(),
),
})
// isLoading을 통해 로딩 여부를 알 수 있음
if (isLoading) return 'Loading...'
// error를 통해 에러 발생 여부를 알 수 있음
if (error) return 'An error has occurred: ' + error.message
return (
<div>
<h1>{data.name}</h1>
<p>{data.description}</p>
<strong>👀 {data.subscribers_count}</strong>{' '}
<strong>✨ {data.stargazers_count}</strong>{' '}
<strong>🍴 {data.forks_count}</strong>
</div>
)
}
값을 변경할 때
사용하는 api// useMutation 활용 코드
const mutation = useMutation({
mutationFn: (newTodo) => {
return axios.post('/todos', newTodo)
},
})
// 전체 예시 코드
function App() {
const mutation = useMutation({
mutationFn: (newTodo) => {
// 처음에 post 비동기 함수를 넣어줌
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={() => {
// 첫 번째 인자로 api 호출 시 전달해야 할 데이터 넣어주기!
mutation.mutate({ id: new Date(), title: 'Do Laundry' })
}}
>
Create Todo
</button>
</>
)}
</div>
)
}
📚 useQuery 동기적 실행
enabled
옵션 사용enabled에 값 대입 → 해당 값이 true일 때 → useQuery 비동기 실행 가능!
const { data: todoList, error, isFetching } = useQuery("todos", fetchTodoList);
const { data: nextTodo, error, isFetching } = useQuery(
"nextTodos",
fetchNextTodoList,
{
enabled: !!todoList // true가 되면 fetchNextTodoList를 실행한다
}
);
📚 useQueries
Promise.all()
처럼 묶어서 실행할 수 있도록 도와주는 역할!const results = useQueries({
queries: [
{ queryKey: ['post', 1], queryFn: fetchPost, staleTime: Infinity},
{ queryKey: ['post', 2], queryFn: fetchPost, staleTime: Infinity}
]
})
📚 retry
retryDelay
: 다음 재요청까지의 딜레이 시간const userQuery = useQuery(['users',1], fetchUsers,
{ retry : 10, retryDelay : 400});
react-query/devtools
를 통해 Devtool 지원 → 확실한 데이터 흐름 파악 가능swr
: devtools 사용 가능하지만, 서드 파티 라이브러리를 이용해야 함!getPreviousPageParam
, fetchPreviousPage
, hasPreviousPage
등의 기능을 활용하여 쉽게 무한 스크롤 구현 가능Selectors
select
를 통해 raw data로 부터 원하는 데이터 추출, 반환
가능import { useQuery } from 'react-query'
function User() {
const { data } = useQuery('user', fetchUser, {
// select 활용
select: user => user.username,
})
return <div>Username: {data}</div>
}
Data Optimization
쿼리가 업데이트
될 때만 refetch
진행여러 컴포넌트
에서 동일한 쿼리 사용 시, 한 번에 묶어
업데이트 진행Garbage Collection
Auto Garbage Collection
→ 메모리 관리