Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 40 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@
4. [React Query 캐싱 라이프 사이클](#캐싱-라이프-사이클)
5. [useQuery](#usequery)
6. [useQuery 주요 리턴 데이터](#usequery-주요-리턴-데이터)
7. [staleTime과 cacheTime](#staletime-cachetime)
7. [staleTime과 cacheTime](#staletime과-cachetime)
8. [마운트 될 때마다 재요청하는 refetchOnMount](#refetchonmount)
9. [윈도우가 포커싱 될 때마다 재요청하는 refetchOnWindowFocus](#refetchonwindowfocus)
10. [Polling 방식을 구현하기 위한 refetchInterval와 refetchIntervalInBackground)](#polling)
11. [자동 실행의 enabled와 수동으로 쿼리를 다시 요청하는 refetch](#enabled-refetch)
12. [실패한 쿼리에 대해 재요청하는 retry](#retry)
13. [onSuccess, onError, onSettled Callback](#onsuccess-onerror-onsettled)
13. [onSuccess, onError, onSettled](#onsuccess-onerror-onsettled)
14. [select를 이용한 데이터 변환](#select)
15. [Paginated 구현에 유용한 keepPreviousData](#keeppreviousdata)
16. [쿼리를 병렬(Parallel) 요청할 수 있는 useQueries](#parallel)
Expand Down Expand Up @@ -176,10 +176,12 @@ import { ReactQueryDevtools } from "react-query/devtools";

- v4부터는 devtools를 위한 별도의 패키지 설치가 필요하다.

```
npm i @tanstack/react-query-devtools
or
yarn add @tanstack/react-query-devtools
```bash
$ npm i @tanstack/react-query-devtools
# or
$ pnpm add @tanstack/react-query-devtools
# or
$ yarn add @tanstack/react-query-devtools
```

```js
Expand Down Expand Up @@ -210,7 +212,7 @@ function App() {
* Garbage Collection(가비지 컬렉션)
```

- cacheTime의 기본값 5분, staleTime 기본값 0분을 가정
- `cacheTime`의 기본값 5분, `staleTime` 기본값 0초를 가정

1. `A`라는 queryKey를 가진 A 쿼리 인스턴스가 `mount`됨
2. 네트워크에서 데이터 fetch하고, 불러온 데이터는 A라는 queryKey로 `캐싱`함
Expand All @@ -225,8 +227,6 @@ function App() {

### useQuery 기본 문법

[목차 이동](#주요-컨셉-및-가이드-목차)

- [useQuery v4](https://tanstack.com/query/v4/docs/react/reference/useQuery)

```jsx
Expand Down Expand Up @@ -316,8 +316,8 @@ const useSuperHeroData = (heroId: string) => {
// 예
const useSuperHeroData = (heroId: string) => {
return useQuery(["super-hero", heroId], () => getSuperHero(heroId), {
staleTime: 3000,
cacheTime: 5000,
cacheTime: 5 * 60 * 1000, // 5분
staleTime: 1 * 60 * 1000, // 1분
retry: 1,
// ...options
});
Expand All @@ -328,8 +328,6 @@ const useSuperHeroData = (heroId: string) => {

### useQuery 주요 리턴 데이터

[목차 이동](#주요-컨셉-및-가이드-목차)

```js
const { status, isLoading, isError, error, data, isFetching, ... } = useQuery(
["colors", pageNum],
Expand Down Expand Up @@ -382,10 +380,9 @@ const { status, isLoading, isError, error, data, isFetching, ... } = useQuery(

[목차 이동](#주요-컨셉-및-가이드-목차)

- [useQuery v4](https://tanstack.com/query/v4/docs/react/reference/useQuery)
- 아래 예제들 제외하고 추가적인 옵션들은 위 사이트 참고
- 추가적인 옵션들은 [useQuery v4 공식 문서](https://tanstack.com/query/v4/docs/react/reference/useQuery) 참고

### staleTime cacheTime
### staleTime과 cacheTime

- stale은 용어 뜻대로 `썩은` 이라는 의미이다. 즉, 최신 상태가 아니라는 의미이다.
- fresh는 뜻 그대로 `신선한` 이라는 의미이다. 즉, 최신 상태라는 의미이다.
Expand All @@ -395,8 +392,8 @@ const { isLoading, isFetching, data, isError, error } = useQuery(
["super-hero"],
getSuperHero,
{
cacheTime: 3000,
staleTime: 50000,
cacheTime: 5 * 60 * 1000, // 5분
staleTime: 1 * 60 * 1000, // 1분
}
);
```
Expand All @@ -423,8 +420,6 @@ const { isLoading, isFetching, data, isError, error } = useQuery(

### refetchOnMount

[목차 이동](#주요-컨셉-및-가이드-목차)

```jsx
const { isLoading, isFetching, data, isError, error } = useQuery(
["super-hero"],
Expand All @@ -444,8 +439,6 @@ const { isLoading, isFetching, data, isError, error } = useQuery(

### refetchOnWindowFocus

[목차 이동](#주요-컨셉-및-가이드-목차)

```jsx
const { isLoading, isFetching, data, isError, error } = useQuery(
["super-hero"],
Expand All @@ -464,8 +457,6 @@ const { isLoading, isFetching, data, isError, error } = useQuery(

### Polling

[목차 이동](#주요-컨셉-및-가이드-목차)

```jsx
const { isLoading, isFetching, data, isError, error } = useQuery(
["super-hero"],
Expand All @@ -486,8 +477,6 @@ const { isLoading, isFetching, data, isError, error } = useQuery(

### enabled refetch

[목차 이동](#주요-컨셉-및-가이드-목차)

```jsx
const { isLoading, isFetching, data, isError, error, refetch } = useQuery(
["super-hero"],
Expand Down Expand Up @@ -520,8 +509,6 @@ return (

### retry

[목차 이동](#주요-컨셉-및-가이드-목차)

```jsx
const result = useQuery(["todos", 1], fetchTodoListPage, {
retry: 10, // 오류를 표시하기 전에 실패한 요청을 10번 재시도합니다.
Expand All @@ -536,9 +523,9 @@ const result = useQuery(["todos", 1], fetchTodoListPage, {

<br />

### onSuccess onError onSettled
### onSuccess, onError, onSettled

[목차 이동](#주요-컨셉-및-가이드-목차)
_NOTE_: 위 Callback은 `useQuery` 옵션에서 [`@Deprecated`되어 삭제될 예정](https://github.com/TanStack/query/pull/5353)(v5에 반영)이다. 단, `useMutation`에서는 사용 가능하다.

```jsx
const onSuccess = useCallback((data) => {
Expand Down Expand Up @@ -572,8 +559,6 @@ const { isLoading, isFetching, data, isError, error, refetch } = useQuery(

### select

[목차 이동](#주요-컨셉-및-가이드-목차)

```jsx
const { isLoading, isFetching, data, isError, error, refetch } = useQuery(
["super-hero"],
Expand Down Expand Up @@ -604,8 +589,6 @@ return (

### keepPreviousData

[목차 이동](#주요-컨셉-및-가이드-목차)

```jsx
const fetchColors = async (pageNum: number) => {
return await axios.get(
Expand All @@ -627,8 +610,6 @@ const { isLoading, isError, error, data, isFetching, isPreviousData } =

### placeholderData

[목차 이동](#주요-컨셉-및-가이드-목차)

```js
function Todos() {
const placeholderData = useMemo(() => generateFakeTodos(), []);
Expand Down Expand Up @@ -932,6 +913,8 @@ refetch({ refetchPage: (page, index) => index === 0 });

## useMutation

[목차 이동](#주요-컨셉-및-가이드-목차)

- [useMutation v4](https://tanstack.com/query/v4/docs/react/reference/useMutation)
- react-query에서 기본적으로 서버에서 데이터를 Get 할 때는 useQuery를 사용한다.
- 만약 서버의 data를 post, patch, put, delete와 같이 수정하고자 한다면 이때는 useMutation을 이용한다.
Expand Down Expand Up @@ -1151,10 +1134,12 @@ const useAddSuperHeroData = () => {

- `useQueryErrorResetBoundary`는 `ErrorBoundary`와 함께 사용되는데 이는, 기본적으로 리액트 공식문서에서 기본 코드 베이스가 제공되긴 하지만 좀 더 쉽게 활용할 수 있는 `react-error-boundary` 라이브러리가 존재하고, react-query 공식문서에서도 해당 라이브러리 사용을 예시로 제공해주기 때문에 `react-error-boundary`를 설치해서 사용해보자.

```
npm i react-error-boundary
또는
yarn add react-error-boundary
```bash
$ npm i react-error-boundary
# or
$ pnpm add react-error-boundary
# or
$ yarn add react-error-boundary
```

- 설치 후에 아래와 같은 QueryErrorBoundary라는 컴포넌트를 생성하고, 그 내부에 `useQueryErrorResetBoundary` 훅을 호출해 `reset` 함수를 가져온다.
Expand Down Expand Up @@ -1323,11 +1308,12 @@ const useSuperHeroData = (heroId: string) => {

### useQuery

- 현재 useQuery가 갖고 있는 제네릭은 `4개`이며, 다음과 같다.
1. TQueryFnData: useQuery로 실행하는 query function의 `실행 결과`의 타입을 지정하는 제네릭 타입이다.
2. TError: query function의 `error` 형식을 정하는 제네릭 타입이다.
3. TData: useQuery의 `data에 담기는 실질적인 데이터`의 타입을 말한다. 첫 번째 제네릭과의 차이점은 `select`와 같이 query function의 반환 데이터를 추가 핸들링을 통해 반환하는 경우에 대응할 수 있는 타입이라고 생각하면 좋다.
4. TQueryKey: useQuery의 첫 번째 인자로 주는 `queryKey`의 타입을 명시적으로 지정해주는 제네릭 타입이다.
현재 useQuery가 갖고 있는 제네릭은 `4개`이며, 다음과 같다.

1. TQueryFnData: useQuery로 실행하는 query function의 `실행 결과`의 타입을 지정하는 제네릭 타입이다.
2. TError: query function의 `error` 형식을 정하는 제네릭 타입이다.
3. TData: useQuery의 `data에 담기는 실질적인 데이터`의 타입을 말한다. 첫 번째 제네릭과의 차이점은 `select`와 같이 query function의 반환 데이터를 추가 핸들링을 통해 반환하는 경우에 대응할 수 있는 타입이라고 생각하면 좋다.
4. TQueryKey: useQuery의 첫 번째 인자로 주는 `queryKey`의 타입을 명시적으로 지정해주는 제네릭 타입이다.

```ts
// useQuery의 타입
Expand Down Expand Up @@ -1362,14 +1348,15 @@ const { data } = useQuery<

### useMutation

- useMutation도 useQuery와 동일하게 현재 4개이며, 다음과 같다.
1. TData: useMutaion에 넘겨준 mutation function의 `실행 결과`의 타입을 지정하는 제네릭 타입이다.
- data의 타입과 onSuccess(1번째 인자)의 인자의 타입으로 활용된다.
2. TError: useMutaion에 넘겨준 mutation function의 `error` 형식을 정하는 제네릭 타입이다.
3. TVariables: `mutate 함수`에 전달 할 인자를 지정하는 제네릭 타입이다.
- onSuccess(2번째 인자), onError(2번째 인자), onMutate(1번째 인자), onSettled(3번째 인자) 인자의 타입으로 활용된다.
4. TContext: mutation function을 실행하기 전에 수행하는 `onMutate 함수의 return값`을 지정하는 제네릭 타입이다.
- onMutate의 결과 값의 타입을 onSuccess(3번째 인자), onError(3번째 인자), onSettled(4번째 인자)에서 활용하려면 해당 타입을 지정해야 한다.
useMutation도 useQuery와 동일하게 현재 4개이며, 다음과 같다.

1. TData: useMutaion에 넘겨준 mutation function의 `실행 결과`의 타입을 지정하는 제네릭 타입이다.
- data의 타입과 onSuccess(1번째 인자)의 인자의 타입으로 활용된다.
2. TError: useMutaion에 넘겨준 mutation function의 `error` 형식을 정하는 제네릭 타입이다.
3. TVariables: `mutate 함수`에 전달 할 인자를 지정하는 제네릭 타입이다.
- onSuccess(2번째 인자), onError(2번째 인자), onMutate(1번째 인자), onSettled(3번째 인자) 인자의 타입으로 활용된다.
4. TContext: mutation function을 실행하기 전에 수행하는 `onMutate 함수의 return값`을 지정하는 제네릭 타입이다.
- onMutate의 결과 값의 타입을 onSuccess(3번째 인자), onError(3번째 인자), onSettled(4번째 인자)에서 활용하려면 해당 타입을 지정해야 한다.

```ts
export function useMutaion<
Expand Down
59 changes: 33 additions & 26 deletions document/v4.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,30 @@
### @tanstack/react-query

- v4부터 react-query에서 `@tanstack/react-query`로 패키지가 변경되었다. 따라서 설치와 import 할 때 주의해야 한다.
- 또한, Devtools는 별도의 패키지 설치가 필요하다.

```
npm i @tanstack/react-query
or
```bash
$ npm i @tanstack/react-query
# or
pnpm add @tanstack/react-query
# or
yarn add @tanstack/react-query
```

```
npm i @tanstack/react-query-devtools
or
yarn add @tanstack/react-query-devtools
- 또한, Devtools는 별도의 패키지 설치가 필요하다.
```bash
$ npm i @tanstack/react-query-devtools
# or
$ pnpm add @tanstack/react-query-devtools
# or
$ yarn add @tanstack/react-query-devtools
```

```js
- import 시, 다음과 같이 패키지명을 수정하면 된다.
```diff
// v3
import { useQuery } from "react-query"; // (-)
import { ReactQueryDevtools } from "react-query/devtools"; // (-)
- import { useQuery } from "react-query";
- import { ReactQueryDevtools } from "react-query/devtools";

// v4
import { useQuery } from "@tanstack/react-query"; // (+)
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; // (+)
+ import { useQuery } from "@tanstack/react-query";
+ import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
```

<br />
Expand All @@ -44,25 +46,27 @@ import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; // (+)

- v3에서는 queryKey를 문자열 또는 배열로 지정할 수 있었다. 문자열과 배열 모두 사용할 수 있었는데 사실 React Query는 내부적으로는 항상 Array Keys로만 작동했었다. 그리고 이를 v4에서는 배열로 통일시킨다.

```js
```diff
// v3
useQuery("todos", fetchTodos); // (-)
- useQuery("todos", fetchTodos);

// v4
useQuery(["todos"], fetchTodos); // (+)
+ useQuery(["todos"], fetchTodos);
```

<br />

### status idle 상태 제거

- v4부터 더 나은 오프라인 지원을위한 fetchStatus가 도입되면서 기존의 `idle`가 무의미해 졌습니다.
- v4부터 더 나은 오프라인 지원을 위한 `fetchStatus`가 도입되면서 기존의 `idle`이 무의미해졌습니다.

```js
status: "idle"; // (-)
```diff
// v3
- status: "idle";

status: "loading"; // (+)
fetchStatus: "idle"; // (+)
// v4
+ status: "loading";
+ fetchStatus: "idle";
```

<br />
Expand Down Expand Up @@ -153,9 +157,12 @@ inactive?: boolean
- 예를 들어 위와 같은 `active`, `inactive` 두 옵션은 서로 `상호 배타적`이다. 이 둘 모두를 false으로 설정한다면? 이는 말이 되지 않는다.
- v4부터는 이를 type이라는 속성으로 통일시켜서 의도를 더 잘 보여줄 수 있게 됐다.

```
```diff
// v3
- active?: boolean
- inactive?: boolean

// v4
+ type?: 'active' | 'inactive' | 'all'
```

Expand Down Expand Up @@ -185,6 +192,6 @@ await queryClient.refetchQueries({ queryKey: ['posts'], type: 'active' })

### 타입스크립트

- v4는 TypeScript `v4.1` 이상을 요구한다.
- [v4는 TypeScript `v4.1` 이상을 요구한다.](https://tanstack.com/query/v4/docs/react/guides/migrating-to-react-query-4#typescript)

<br />