- )
-}
-```
-
-```tsx Example.tsx
-import { Suspense } from '@suspensive/react'
-import { PostList } from './PostList'
-
-export const Example = () => {
- return (
- Loading...}>
-
-
- )
-}
-```
-
-```tsx api.ts
-type Post = {
- userId: number
- id: number
- title: string
- body: string
-}
-
-export const getPosts = async (
- page: number
-): Promise<{
- data: Post[]
- page: number
- total: number
- limit: number
- skip: number
-}> => {
- const response = await fetch(
- `https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=10`
- )
-
- if (!response.ok) {
- throw new Error('An error occurred')
- }
-
- const data = await response.json()
-
- return {
- data,
- page,
- total: 100,
- limit: 10,
- skip: (page - 1) * 10,
- }
-}
-```
-
-
-
-### Motivation
-
-If you turn suspense on in @tanstack/react-query, You can use [useInfiniteQuery](https://tanstack.com/query/v4/docs/react/reference/useInfiniteQuery) with `` and ``.
-
-```tsx /useInfiniteQuery/
-import { useInfiniteQuery } from '@tanstack/react-query'
-
-const Example = () => {
- const query = useInfiniteQuery({
- queryKey,
- queryFn,
- suspense: true,
- })
-
- query.data // InfiniteData | undefined
-
- if (query.isSuccess) {
- query.data // InfiniteData
- }
-}
-```
-
-but useInfiniteQuery's return type query.data will always be fulfilled because of `` as parent of this component.
-
-This is why @suspensive/react-query provide **useSuspenseInfiniteQuery**.
-
-
-
-Focus on successful cases.
-
-Now we can focus on the component, as data fetching will always succeed.
-
-
-
-### Version History
-
-| Version | Changes |
-| -------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
-| `v3.0.0` | `networkMode` has been fixed to `'always'`. For more details, please refer to the [Migration to v3 guide](./migration/migrate-to-v3.mdx). |
diff --git a/docs/suspensive.org/src/content/en/docs/react-query/useSuspenseQueries.mdx b/docs/suspensive.org/src/content/en/docs/react-query/useSuspenseQueries.mdx
deleted file mode 100644
index 36a73a11a..000000000
--- a/docs/suspensive.org/src/content/en/docs/react-query/useSuspenseQueries.mdx
+++ /dev/null
@@ -1,194 +0,0 @@
----
-robots: noindex
-description: 'Deprecated — useSuspenseQueries is now available in TanStack Query v4.40.0+. Use the official TanStack Query version instead.'
----
-
-import { Callout, Sandpack } from '@/components'
-
-# useSuspenseQueries
-
-
-
-**Deprecated in @suspensive/react-query**
-
-This hook is now officially supported in TanStack Query v4.40.0+. Since TanStack Query has backported this interface, we are deprecating the backported version from @suspensive/react-query. Please migrate to the official TanStack Query interface:
-
-```diff
-- import { useSuspenseQueries } from '@suspensive/react-query'
-+ import { useSuspenseQueries } from '@tanstack/react-query'
-```
-
-For more details, see [TanStack Query PR #9140](https://github.com/TanStack/query/pull/9140).
-
-
-
-There is no isLoading or isError in the return type of this hook. This is because `` and `` guarantee the data of this hook. Also, in the options of this hook, suspense is set to true by default. You can use @tanstack/react-query's [useQueries](https://tanstack.com/query/v4/docs/react/reference/useQueries) for the new options you need.
-
-```tsx /useSuspenseQueries/
-import { useSuspenseQueries } from '@suspensive/react-query'
-
-const Example = () => {
- const [query1, query2] = useSuspenseQueries({
- queries: [
- { queryKey: [1], queryFn },
- { queryKey: [2], queryFn },
- ],
- }) // suspense: true is the default.
-
- // No type narrowing required with isSuccess.
- query1.data // TData
- query2.data // TData
-}
-```
-
-
-
-```tsx Post.tsx active
-import { useSuspenseQueries } from '@suspensive/react-query'
-import { getPost, getComments } from './api'
-
-export const Post = ({ postId }: { postId: number }) => {
- const [postQuery, commentQuery] = useSuspenseQueries({
- queries: [
- { queryKey: ['posts', postId], queryFn: () => getPost(postId) },
- { queryKey: ['comments', postId], queryFn: () => getComments(postId) },
- ],
- })
-
- return (
-
-
{postQuery.data.title}
-
{postQuery.data.body}
-
Comments
-
- {commentQuery.data.map((comment) => (
-
{comment.body}
- ))}
-
-
- )
-}
-```
-
-```tsx Example.tsx
-import { Suspense } from '@suspensive/react'
-import { useState } from 'react'
-import { Post } from './Post'
-
-export const Example = () => {
- const [postId, setPostId] = useState(1)
-
- return (
-
-
-
- Loading...
}>
-
-
-
- )
-}
-```
-
-```tsx /api.ts
-type Post = {
- userId: number
- id: number
- title: string
- body: string
-}
-
-export const getPost = async (id: number): Promise => {
- const response = await fetch(
- `https://jsonplaceholder.typicode.com/posts/${id}`
- )
-
- if (!response.ok) {
- throw new Error('An error occurred')
- }
-
- const data = await response.json()
-
- return data
-}
-
-type Comment = {
- postId: number
- id: number
- name: string
- email: string
- body: string
-}
-
-export const getComments = async (postId: number): Promise => {
- const response = await fetch(
- `https://jsonplaceholder.typicode.com/comments?postId=${postId}`
- )
-
- if (!response.ok) {
- throw new Error('An error occurred')
- }
-
- const data = await response.json()
-
- return data
-}
-```
-
-
-
-### Motivation
-
-You can use [useQueries](https://tanstack.com/query/v4/docs/react/reference/useQueries) with `` and `` by using the suspense option of @tanstack/react-query useQueries.
-
-```tsx /useQueries/
-import { useQueries } from '@tanstack/react-query'
-
-const Example = () => {
- const [query1, query2] = useQueries({
- queries: [
- { queryKey: [1], queryFn, suspense: true },
- { queryKey: [2], queryFn, suspense: true },
- ],
- })
-
- query1.data // TData | undefined
- query2.data // TData | undefined
-
- if (query1.isSuccess) {
- query1.data // TData
- }
- if (query2.isSuccess) {
- query2.data // TData
- }
-}
-```
-
-The return type of useQueries (query1.data, query2.data) will always be a success case thanks to this component's parents, `` and ``.
-But @tanstack/react-query doesn't express this in its TypeScript types.
-
-That's why @suspensive/react-query provides **useSuspenseQueries**.
-
-
-
-Focus on successful cases.
-
-Now we can focus only on successful cases as fetching always succeeds inside our component.
-
-
-
-### Version History
-
-| Version | Changes |
-| -------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
-| `v3.0.0` | `networkMode` has been fixed to `'always'`. For more details, please refer to the [Migration to v3 guide](./migration/migrate-to-v3.mdx). |
diff --git a/docs/suspensive.org/src/content/en/docs/react-query/useSuspenseQuery.mdx b/docs/suspensive.org/src/content/en/docs/react-query/useSuspenseQuery.mdx
deleted file mode 100644
index 6fc403ecd..000000000
--- a/docs/suspensive.org/src/content/en/docs/react-query/useSuspenseQuery.mdx
+++ /dev/null
@@ -1,156 +0,0 @@
----
-robots: noindex
-description: 'Deprecated — useSuspenseQuery is now available in TanStack Query v4.40.0+. Use the official TanStack Query version instead.'
----
-
-import { Callout, Sandpack } from '@/components'
-
-# useSuspenseQuery
-
-
-
-**Deprecated in @suspensive/react-query**
-
-This hook is now officially supported in TanStack Query v4.40.0+. Since TanStack Query has backported this interface, we are deprecating the backported version from @suspensive/react-query. Please migrate to the official TanStack Query interface:
-
-```diff
-- import { useSuspenseQuery } from '@suspensive/react-query'
-+ import { useSuspenseQuery } from '@tanstack/react-query'
-```
-
-For more details, see [TanStack Query PR #9140](https://github.com/TanStack/query/pull/9140).
-
-
-
-There is no isLoading or isError in the return type of this hook. This is because `` and `` guarantee the data of this hook. Also, in the options of this hook, suspense is set to true by default. Any new options you need can be used like @tanstack/react-query's [useQuery](https://tanstack.com/query/v4/docs/react/reference/useQuery).
-
-```tsx /useSuspenseQuery/
-import { useSuspenseQuery } from '@suspensive/react-query'
-
-const Example = () => {
- const query = useSuspenseQuery({
- queryKey,
- queryFn,
- }) // suspense: true is the default.
-
- // No type narrowing required with isSuccess.
- query.data // TData
-}
-```
-
-
-
-```tsx Post.tsx active
-import { useSuspenseQuery } from '@suspensive/react-query'
-import { getPost } from './api'
-
-export const Post = ({ postId }: { postId: number }) => {
- const { data } = useSuspenseQuery({
- queryKey: ['posts', postId],
- queryFn: () => getPost(postId),
- })
-
- return (
-
-
{data.title}
-
{data.body}
-
- )
-}
-```
-
-```tsx Example.tsx
-import { Suspense } from '@suspensive/react'
-import { useState } from 'react'
-import { Post } from './Post'
-
-export const Example = () => {
- const [postId, setPostId] = useState(1)
-
- return (
-
-
-
- Loading...
}>
-
-
-
- )
-}
-```
-
-```tsx /api.ts
-type Post = {
- userId: number
- id: number
- title: string
- body: string
-}
-
-export const getPost = async (id: number): Promise => {
- const response = await fetch(
- `https://jsonplaceholder.typicode.com/posts/${id}`
- )
-
- if (!response.ok) {
- throw new Error('An error occurred')
- }
-
- const data = await response.json()
-
- return data
-}
-```
-
-
-
-### Motivation
-
-You can use [useQuery](https://tanstack.com/query/v4/docs/react/reference/useQuery) with `` and `` by using the suspense option in @tanstack/react-query.
-
-```tsx /useQuery/
-import { useQuery } from '@tanstack/react-query'
-
-const Example = () => {
- const query = useQuery({
- queryKey,
- queryFn,
- suspense: true,
- })
-
- query.data // TData | undefined
-
- if (query.isSuccess) {
- query.data // TData
- }
-}
-```
-
-The return type of useQuery (query.data) will always be a success case thanks to this component's parents, `` and ``.
-But @tanstack/react-query doesn't express this in its TypeScript types.
-
-That's why @suspensive/react-query provides **useSuspenseQuery**.
-
-
-
-Focus on successful cases.
-
-Now we can focus only on successful cases as fetching always succeeds inside our component.
-
-
-
-### Version History
-
-| Version | Changes |
-| -------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
-| `v3.0.0` | `networkMode` has been fixed to `'always'`. For more details, please refer to the [Migration to v3 guide](./migration/migrate-to-v3.mdx). |
diff --git a/docs/suspensive.org/src/content/ko/docs/codemods/_meta.tsx b/docs/suspensive.org/src/content/ko/docs/codemods/_meta.tsx
index 829f1d2b9..46c10ff30 100644
--- a/docs/suspensive.org/src/content/ko/docs/codemods/_meta.tsx
+++ b/docs/suspensive.org/src/content/ko/docs/codemods/_meta.tsx
@@ -7,6 +7,7 @@ export default {
type: 'separator',
title: 'Codemods',
},
+ migrateToV4: { title: 'v4로 마이그레이션' },
tanstackQueryImport: { title: 'TanStack Query로 import 경로 변경' },
migrateQueryClientConsumerProps: {
title: ' Props 변환',
diff --git a/docs/suspensive.org/src/content/ko/docs/codemods/migrateToV4.mdx b/docs/suspensive.org/src/content/ko/docs/codemods/migrateToV4.mdx
new file mode 100644
index 000000000..f1a51ba38
--- /dev/null
+++ b/docs/suspensive.org/src/content/ko/docs/codemods/migrateToV4.mdx
@@ -0,0 +1,63 @@
+---
+description: '@suspensive/react-query v4의 브레이킹 체인지를 대응하는 코드모드.'
+---
+
+import { Callout } from '@/components'
+
+# v4로 마이그레이션
+
+
+
+- `@suspensive/react-query` v3 환경에서 v4로 업데이트할 때 추천합니다.
+- `package.json`을 수정하지 않습니다. 실행 후 의존성에서 `@suspensive/react-query`를 제거하고 `@suspensive/react-query-4` 또는 `@suspensive/react-query-5`가 설치되어 있는지 확인하세요.
+
+
+
+`@suspensive/react-query` v4의 코드 레벨 브레이킹 체인지는 두 가지입니다.
+
+1. 통합 패키지 `@suspensive/react-query`가 제거됩니다. 모든 import는 버전별 패키지 `@suspensive/react-query-4` 또는 `@suspensive/react-query-5`를 가리켜야 합니다.
+2. `@tanstack/react-query`에서 제공되는 API(`queryOptions`, `mutationOptions` 등)는 `@suspensive/react-query-4, 5`에서도 제거됩니다. 이들은 `@tanstack/react-query`에서 직접 import 해야 합니다.
+
+```bash filename="Terminal"
+npx @suspensive/codemods migrate-to-v4 .
+```
+
+예:
+
+```tsx /@suspensive/react-query/ /@suspensive/react-query-5/
+import {
+ useSuspenseQuery,
+ SuspenseQuery,
+ queryOptions,
+ IsFetching,
+} from '@suspensive/react-query'
+import { queryOptions, PrefetchQuery } from '@suspensive/react-query-5'
+import * as RQ from '@suspensive/react-query'
+export { queryOptions, QueryClientConsumer } from '@suspensive/react-query'
+```
+
+변환 후:
+
+```tsx /@tanstack/react-query/ /@suspensive/react-query-5/
+import { useSuspenseQuery, queryOptions } from '@tanstack/react-query'
+import { SuspenseQuery, IsFetching } from '@suspensive/react-query-5'
+import { queryOptions } from '@tanstack/react-query'
+import { PrefetchQuery } from '@suspensive/react-query-5'
+import * as RQ from '@suspensive/react-query-5'
+export { queryOptions } from '@tanstack/react-query'
+export { QueryClientConsumer } from '@suspensive/react-query-5'
+```
+
+## 버전 감지
+
+현재 작업 디렉토리에서 위로 올라가며 가장 가까운 `package.json`을 확인해 `@tanstack/react-query`의 v4와 v5 중 어느 버전에 의존하는지 판단합니다. 감지된 메이저 버전은 `@suspensive/react-query`를 버전별 source 로 재작성할 때 사용됩니다.
+
+감지에 실패한 경우 v5로 fallback 하며 경고를 출력합니다. 명시적으로 대상을 지정하려면 실행 전 `SUSPENSIVE_RQ_TARGET` 환경 변수를 `4` 또는 `5`로 설정합니다.
+
+```bash filename="Terminal"
+SUSPENSIVE_RQ_TARGET=4 npx @suspensive/codemods migrate-to-v4 .
+```
+
+## 주의사항
+
+- `package.json`을 수정하지 않습니다. 실행 후 의존성에서 `@suspensive/react-query`를 제거하고 `@suspensive/react-query-4` 또는 `@suspensive/react-query-5`가 설치되어 있는지 확인하세요.
diff --git a/docs/suspensive.org/src/content/ko/docs/codemods/tanstackQueryImport.mdx b/docs/suspensive.org/src/content/ko/docs/codemods/tanstackQueryImport.mdx
index b290d0f81..a96de308c 100644
--- a/docs/suspensive.org/src/content/ko/docs/codemods/tanstackQueryImport.mdx
+++ b/docs/suspensive.org/src/content/ko/docs/codemods/tanstackQueryImport.mdx
@@ -8,12 +8,13 @@ import { Callout } from '@/components'
-- `@suspensive/react-query` & `@tanstack/react-query@4` 환경에서 `@tanstack/react-query@5`로 업데이트 하는 경우 추천합니다.
-- `@suspensive/react-query-4@3.3.0`부터 `queryOptions`, `infiniteQueryOption`, `useSuspenseQuery`, `useSuspenseQueries`가 deprecated 되었습니다. (`@tanstack/react-query@4.40.0` 버전에서 공식적으로 `useSuspenseQuery`, `queryOptions` 지원합니다.)
+- `@suspensive/react-query`, `@suspensive/react-query-4`, `@suspensive/react-query-5`에서 `@tanstack/react-query` API로 전환하고자 할 때 추천합니다.
+- v4에서는 `@tanstack/react-query`에 제공되는 API들이 `@suspensive/react-query-4,5`에서 제거됩니다. `@tanstack/react-query`로 전환하고자 할 때 추천합니다.
-`@suspensive/react-query`의 API 중 `@tanstack/react-query`에서 공식 제공하는 API일 경우 `deprecated`로 표시됩니다.
+`@suspensive/react-query`의 API 중 `@tanstack/react-query`에서 공식 제공하는 API일 경우 `deprecated`로 표시됩니다.
+
이는 `@tanstack/react-query`에 동일한 API인 Suspense Hooks와 `queryOptions`, `infiniteQueryOption`을 `@suspensive/react-query`가 제공하고 있어, 개발자가 `@tanstack/react-query`의 API를 우선적으로 사용하도록 유도하기 위함입니다.
```bash filename="Terminal"
@@ -25,13 +26,18 @@ npx @suspensive/codemods tanstack-query-import .
예:
```tsx /@suspensive/
-import { queryOptions } from '@suspensive/react-query'
-import { useSuspenseQuery } from '@suspensive/react-query-5' // 버전 패키지도 변환됩니다!
+import {
+ queryOptions,
+ mutationOptions,
+ SuspenseQuery,
+} from '@suspensive/react-query-5'
+import { useSuspenseQuery } from '@suspensive/react-query'
```
변환 후:
```tsx /@tanstack/
-import { queryOptions } from '@tanstack/react-query'
+import { queryOptions, mutationOptions } from '@tanstack/react-query'
+import { SuspenseQuery } from '@suspensive/react-query-5'
import { useSuspenseQuery } from '@tanstack/react-query'
```
diff --git a/docs/suspensive.org/src/content/ko/docs/react-query/_meta.tsx b/docs/suspensive.org/src/content/ko/docs/react-query/_meta.tsx
index 344458421..86a30e1cd 100644
--- a/docs/suspensive.org/src/content/ko/docs/react-query/_meta.tsx
+++ b/docs/suspensive.org/src/content/ko/docs/react-query/_meta.tsx
@@ -4,10 +4,12 @@ import type MetaEn from '../../../en/docs/react-query/_meta'
export default {
motivation: { title: '동기' },
installation: { title: '설치하기' },
+ migration: { title: '마이그레이션 가이드' },
'--- API Reference': {
type: 'separator',
title: 'API 문서',
},
+ createGetQueryClient: { title: 'createGetQueryClient' },
SuspenseQuery: { title: '' },
SuspenseQueries: { title: '' },
SuspenseInfiniteQuery: { title: '' },
@@ -17,22 +19,4 @@ export default {
QueriesHydration: { title: '' },
QueryClientConsumer: { title: '' },
IsFetching: { title: '' },
- createGetQueryClient: { title: 'createGetQueryClient' },
- usePrefetchQuery: { title: 'usePrefetchQuery' },
- usePrefetchInfiniteQuery: { title: 'usePrefetchInfiniteQuery' },
- '--- Deprecated': {
- type: 'separator',
- title: 'Deprecated',
- },
- queryOptions: { title: 'queryOptions' },
- mutationOptions: { title: 'mutationOptions' },
- infiniteQueryOptions: { title: 'infiniteQueryOptions' },
- useSuspenseQuery: { title: 'useSuspenseQuery' },
- useSuspenseQueries: { title: 'useSuspenseQueries' },
- useSuspenseInfiniteQuery: { title: 'useSuspenseInfiniteQuery' },
- '--- More': {
- type: 'separator',
- title: '더보기',
- },
- migration: { title: '마이그레이션 가이드' },
} satisfies typeof MetaEn satisfies MetaRecord
diff --git a/docs/suspensive.org/src/content/ko/docs/react-query/infiniteQueryOptions.mdx b/docs/suspensive.org/src/content/ko/docs/react-query/infiniteQueryOptions.mdx
deleted file mode 100644
index de3e48152..000000000
--- a/docs/suspensive.org/src/content/ko/docs/react-query/infiniteQueryOptions.mdx
+++ /dev/null
@@ -1,164 +0,0 @@
----
-robots: noindex
----
-
-import { Callout, Sandpack } from '@/components'
-
-# infiniteQueryOptions
-
-
-
-**@suspensive/react-query에서 Deprecated**
-
-이 인터페이스는 이제 TanStack Query v4.41.0+에서 공식적으로 지원됩니다. TanStack Query에서 백포팅했으므로, @suspensive/react-query의 백포팅된 버전을 deprecated 처리합니다. 공식 TanStack Query 인터페이스로 마이그레이션하세요:
-
-```diff
-- import { infiniteQueryOptions } from '@suspensive/react-query'
-+ import { infiniteQueryOptions } from '@tanstack/react-query'
-```
-
-자세한 내용은 [TanStack Query PR #9334](https://github.com/TanStack/query/pull/9334)을 참고하세요.
-
-
-
-`infiniteQueryOptions`는 Infinite Query에서 queryOptions를 활용할 수 있도록 도와줍니다. 이는 [`queryOptions`](https://suspensive.org/ko/docs/react-query/queryOptions)가 사용되는 이유와 유사한 장점을 제공합니다.
-
-```jsx /infiniteQueryOptions/
-import { infiniteQueryOptions, useSuspenseInfiniteQuery, SuspenseInfiniteQuery } from '@suspensive/react-query'
-import { useInfiniteQuery, useQueryClient } from '@tanstack/react-query'
-
-const postsInfiniteQueryOptions = (page) =>
- infiniteQueryOptions({
- queryKey: ['posts', page] as const,
- queryFn: ({
- queryKey: [, page], // queryKey를 활용할 수 있습니다.
- }) => fetch(`https://example.com/posts?page=${page}`).then(res => res.json()),
- getNextPageParam: (lastPage) => lastPage.nextPage ?? false,
- })
-
-// 커스텀 쿼리 훅을 만들 필요가 없습니다.
-// useInfiniteQuery, useSuspenseInfiniteQuery, SuspenseInfiniteQuery에서 직접 infiniteQueryOptions를 활용할 수 있습니다.
-const postsQuery = useInfiniteQuery(postsInfiniteQueryOptions(1))
-const { data: posts, fetchNextPage, hasNextPage } = useSuspenseInfiniteQuery({
- ...postsInfiniteQueryOptions(1),
- refetchInterval: 2000, // 사용처에서 확장성을 명확히 표현됩니다.
-})
-const Example = () => (
-
- {({ data, fetchNextPage, hasNextPage }) => (
-