diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73942933e4..7d89f132b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: fetch-depth: '0' - uses: pnpm/action-setup@v2.2.4 with: - version: 7 + version: 8 - uses: actions/setup-node@v3 with: node-version: 18.16.0 diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index f7b4dbb2e1..5df318e69d 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -19,7 +19,7 @@ jobs: repository: ${{github.event.pull_request.head.repo.full_name}} - uses: pnpm/action-setup@v2.2.4 with: - version: 7 + version: 8 - uses: actions/setup-node@v3 with: node-version: 18.16.0 @@ -39,7 +39,7 @@ jobs: repository: ${{github.event.pull_request.head.repo.full_name}} - uses: pnpm/action-setup@v2.2.4 with: - version: 7 + version: 8 - uses: actions/setup-node@v3 with: node-version: 18.16.0 @@ -76,7 +76,7 @@ jobs: repository: ${{github.event.pull_request.head.repo.full_name}} - uses: pnpm/action-setup@v2.2.4 with: - version: 7 + version: 8 - uses: actions/setup-node@v3 with: node-version: 18.16.0 diff --git a/docs/config.json b/docs/config.json index 4c4bc27ea2..29e2ac321b 100644 --- a/docs/config.json +++ b/docs/config.json @@ -208,6 +208,10 @@ { "label": "Angular Query", "to": "react/community/angular-query" + }, + { + "label": "Suspensive React Query", + "to": "react/community/suspensive-react-query" } ] }, diff --git a/docs/react/community/suspensive-react-query.md b/docs/react/community/suspensive-react-query.md new file mode 100644 index 0000000000..07e9730e64 --- /dev/null +++ b/docs/react/community/suspensive-react-query.md @@ -0,0 +1,69 @@ +--- +id: suspensive-react-query +title: Suspensive React Query +--- + +Typesafe useQuery, useInfiniteQuery with default suspense option. + +Use @suspensive/react-query, delegate loading and error handling to the outside of the component with useSuspenseQuery and useSuspenseInfiniteQuery, and focus on success inside the component. + +You don't even need to use the isSuccess flag. + +## Installation +You can install @suspensive/react-query via [NPM](https://www.npmjs.com/package/@suspensive/react-query). + +```bash +$ npm i @suspensive/react @suspensive/react-query +# or +$ pnpm add @suspensive/react @suspensive/react-query +# or +$ yarn add @suspensive/react @suspensive/react-query +``` + +### Motivation + +If you turn suspense mode on in @tanstack/react-query, You can use useQuery with Suspense and ErrorBoundary. + +```tsx +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 + } +} +``` + +Typically query.data will be `TData | undefined` like this code example. +But actual useQuery's return type:query.data will be always fulfilled because of [Suspense](https://suspensive.org/docs/react/src/Suspense.i18n) and [ErrorBoundary](https://suspensive.org/docs/react/src/ErrorBoundary.i18n) as parent of this component. + +This is why @suspensive/react-query provide **useSuspenseQuery** + +## useSuspenseQuery + +Return type of this hook have no isLoading, isError property. because Suspense and ErrorBoundary will guarantee this hook's data. + +In addition, this hook's options have default suspense: true. and you can provide new options to this hook like useQuery of @tanstack/react-query. + +```tsx +import { useSuspenseQuery } from '@suspensive/react-query' + +const Example = () => { + const query = useSuspenseQuery(queryKey, queryFn, options) // suspense:true is default. + + // No need to do type narrowing by isSuccess + query.data // TData +} +``` + +### Concentrate on only Success + +Now, we can concentrate component as any fetching will be always success in component. + +Check the complete documentation on [GitHub](https://github.com/suspensive/react). diff --git a/docs/react/guides/ssr.md b/docs/react/guides/ssr.md index b416336ee5..02d80fd3fb 100644 --- a/docs/react/guides/ssr.md +++ b/docs/react/guides/ssr.md @@ -302,19 +302,19 @@ ReactDOM.hydrate( ## Using the `app` Directory in Next.js 13 -Both prefetching approaches, using `initialData` or ``, are available within the `app` directory. +Both prefetching approaches, using `initialData` or ``, are available within the `app` directory. - Prefetch the data in a Server Component and prop drill `initialData` to Client Components - Quick to set up for simple cases - May need to prop drill through multiple layers of Client Components - May need to prop drill to multiple Client Components using the same query - Query refetching is based on when the page loads instead of when the data was prefetched on the server -- Prefetch the query on the server, dehydrate the cache and rehydrate it on the client with `` +- Prefetch the query on the server, dehydrate the cache and rehydrate it on the client with `` - Requires slightly more setup up front - No need to prop drill - Query refetching is based on when the query was prefetched on the server -### `` is required by both the `initialData` and `` prefetching approaches +### `` is required by both the `initialData` and `` prefetching approaches The hooks provided by the `react-query` package need to retrieve a `QueryClient` from their context. Wrap your component tree with `` and pass it an instance of `QueryClient`. @@ -379,7 +379,7 @@ export function Posts(props) { } ``` -### Using `` +### Using `` Create a request-scoped singleton instance of `QueryClient`. **This ensures that data is not shared between different users and requests, while still only creating the QueryClient once per request.** @@ -397,30 +397,33 @@ Fetch your data in a Server Component higher up in the component tree than the C - Retrieve the `QueryClient` singleton instance - Prefetch the data using the client's prefetchQuery method and wait for it to complete - Use `dehydrate` to obtain the dehydrated state of the prefetched queries from the query cache -- Wrap the component tree that needs the prefetched queries inside ``, and provide it with the dehydrated state -- You can fetch inside multiple Server Components and use `` in multiple places +- Wrap the component tree that needs the prefetched queries inside ``, and provide it with the dehydrated state +- You can fetch inside multiple Server Components and use `` in multiple places > NOTE: TypeScript currently complains of a type error when using async Server Components. As a temporary workaround, use `{/* @ts-expect-error Server Component */}` when calling this component inside another. For more information, see [End-to-End Type Safety](https://beta.nextjs.org/docs/configuring/typescript#end-to-end-type-safety) in the Next.js 13 beta docs. ```tsx // app/hydratedPosts.jsx -import { dehydrate, Hydrate } from '@tanstack/react-query' +import { dehydrate, HydrationBoundary } from '@tanstack/react-query' import getQueryClient from './getQueryClient' export default async function HydratedPosts() { const queryClient = getQueryClient() - await queryClient.prefetchQuery(['posts'], getPosts) + + await queryClient.prefetchQuery({querykey:['posts'], queryFn:getPosts}) + // for infinite queries with useInfiniteQuery use + // await queryClient.prefetchInfiniteQuery({queryKey:['posts'], queryFn:getPosts,...}) const dehydratedState = dehydrate(queryClient) return ( - + - + ) } ``` -During server rendering, calls to `useQuery` nested within the `` Client Component will have access to prefetched data provided in the state property. +During server rendering, calls to `useQuery` nested within the `` Client Component will have access to prefetched data provided in the state property. ```tsx // app/posts.jsx diff --git a/docs/react/plugins/persistQueryClient.md b/docs/react/plugins/persistQueryClient.md index e673c33813..2f116599fc 100644 --- a/docs/react/plugins/persistQueryClient.md +++ b/docs/react/plugins/persistQueryClient.md @@ -212,10 +212,11 @@ ReactDOM.createRoot(rootElement).render( - `persistOptions: PersistQueryClientOptions` - all [options](#options) you can pass to [persistQueryClient](#persistqueryclient) minus the QueryClient itself -- `onSuccess?: () => void` +- `onSuccess?: () => Promise | unknown` - optional - will be called when the initial restore is finished - can be used to [resumePausedMutations](../reference/QueryClient#queryclientresumepausedmutations) + - if a Promise is returned, it will be awaited; restoring is seen as ongoing until then ### useIsRestoring diff --git a/docs/react/reference/useQuery.md b/docs/react/reference/useQuery.md index ec4eb6448d..9d238dd26a 100644 --- a/docs/react/reference/useQuery.md +++ b/docs/react/reference/useQuery.md @@ -11,14 +11,15 @@ const { errorUpdatedAt, failureCount, failureReason, + fetchStatus, isError, isFetched, isFetchedAfterMount, isFetching, - isPaused, - isLoading, isInitialLoading, + isLoading, isLoadingError, + isPaused, isPending, isPlaceholderData, isRefetchError, @@ -27,7 +28,6 @@ const { isSuccess, refetch, status, - fetchStatus, } = useQuery({ queryKey, queryFn, diff --git a/docs/solid/overview.md b/docs/solid/overview.md index 0e74b3e331..99d904a363 100644 --- a/docs/solid/overview.md +++ b/docs/solid/overview.md @@ -129,20 +129,21 @@ export default function App() { function Example() { // ❌ react version -- supports destructing outside reactive context // const { isPending, error, data } = useQuery({ - // queryKey: ['repoData'], () => - // queryFn: fetch('https://api.github.com/repos/tannerlinsley/react-query').then(res => - // res.json() - // ) + // queryKey: ['repoData'], + // queryFn: () => + // fetch('https://api.github.com/repos/tannerlinsley/react-query').then( + // (res) => res.json() + // ), // }) // ✅ solid version -- does not support destructuring outside reactive context - const query = createQuery({ - queryKey: () => ['repoData'], + const query = createQuery(() => ({ + queryKey: ['repoData'], queryFn: () => fetch('https://api.github.com/repos/tannerlinsley/react-query').then( - (res) => res.json(), + (res) => res.json() ), - }) + })) // ✅ access query properties in JSX reactive context return ( diff --git a/docs/svelte/overview.md b/docs/svelte/overview.md index 03d840dae6..978ab543d5 100644 --- a/docs/svelte/overview.md +++ b/docs/svelte/overview.md @@ -64,7 +64,7 @@ Svelte Query offers useful functions and components that will make managing serv - `useIsMutating` - `useHydrate` - `` -- `` +- `` ## Important Differences between Svelte Query & React Query diff --git a/examples/react/algolia/package.json b/examples/react/algolia/package.json index 79a1f282b6..e2dc6611ae 100644 --- a/examples/react/algolia/package.json +++ b/examples/react/algolia/package.json @@ -8,21 +8,21 @@ "preview": "vite preview" }, "dependencies": { - "@tanstack/react-query": "^4.7.1", - "@tanstack/react-query-devtools": "^4.7.1", - "@algolia/client-search": "4.11.0", - "@algolia/transporter": "4.11.0", - "algoliasearch": "4.12.2" + "@algolia/client-search": "4.17.1", + "@algolia/transporter": "4.17.1", + "@tanstack/react-query": "^5.0.0-alpha.38", + "@tanstack/react-query-devtools": "^5.0.0-alpha.38", + "algoliasearch": "4.17.1" }, "devDependencies": { - "@tanstack/eslint-plugin-query": "^4.13.0", - "@vitejs/plugin-react": "^2.0.0", - "vite": "^3.0.0", + "@tanstack/eslint-plugin-query": "^5.0.0-alpha.36", + "@types/react": "^18.2.4", + "@types/react-dom": "^18.2.4", + "@vitejs/plugin-react": "^4.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", - "typescript": "^4.7.4", - "@types/react": "^18.0.14", - "@types/react-dom": "^18.0.5" + "typescript": "^5.0.4", + "vite": "^4.2.0" }, "browserslist": { "production": [ diff --git a/examples/react/auto-refetching/package.json b/examples/react/auto-refetching/package.json index 7cb54af370..be0ab8b40a 100644 --- a/examples/react/auto-refetching/package.json +++ b/examples/react/auto-refetching/package.json @@ -4,13 +4,13 @@ "main": "index.js", "license": "MIT", "dependencies": { - "axios": "^0.21.1", - "isomorphic-unfetch": "3.0.0", - "next": "12.2.2", + "@tanstack/react-query": "^5.0.0-alpha.38", + "@tanstack/react-query-devtools": "^5.0.0-alpha.38", + "axios": "^1.4.0", + "isomorphic-unfetch": "4.0.2", + "next": "^13.4.4", "react": "^18.2.0", - "react-dom": "^18.2.0", - "@tanstack/react-query": "^4.7.1", - "@tanstack/react-query-devtools": "^4.7.1" + "react-dom": "^18.2.0" }, "scripts": { "dev": "next", diff --git a/examples/react/basic-graphql-request/package.json b/examples/react/basic-graphql-request/package.json index c93416d645..63e969decc 100644 --- a/examples/react/basic-graphql-request/package.json +++ b/examples/react/basic-graphql-request/package.json @@ -8,16 +8,16 @@ "preview": "vite preview" }, "dependencies": { - "graphql": "^15.3.0", - "graphql-request": "^3.1.0", - "react": "^18.0.0", - "react-dom": "^18.0.0", - "@tanstack/react-query": "^4.7.1", - "@tanstack/react-query-devtools": "^4.7.1" + "graphql": "^16.6.0", + "graphql-request": "^6.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "@tanstack/react-query": "^5.0.0-alpha.38", + "@tanstack/react-query-devtools": "^5.0.0-alpha.38" }, "devDependencies": { - "@vitejs/plugin-react": "^2.0.0", - "vite": "^3.0.0" + "@vitejs/plugin-react": "^4.0.0", + "vite": "^4.2.0" }, "browserslist": { "production": [ diff --git a/examples/react/basic-typescript/package.json b/examples/react/basic-typescript/package.json index c1a360fa69..304cfe3362 100644 --- a/examples/react/basic-typescript/package.json +++ b/examples/react/basic-typescript/package.json @@ -8,23 +8,23 @@ "preview": "vite preview" }, "dependencies": { - "axios": "^0.26.1", - "react": "^18.0.0", - "react-dom": "^18.0.0", - "@tanstack/react-query": "^4.7.1", - "@tanstack/react-query-devtools": "^4.7.1", - "@tanstack/react-query-persist-client": "^4.7.1", - "@tanstack/query-sync-storage-persister": "^4.7.1" + "@tanstack/react-query": "^5.0.0-alpha.38", + "@tanstack/react-query-devtools": "^5.0.0-alpha.38", + "@tanstack/react-query-persist-client": "^5.0.0-alpha.38", + "@tanstack/query-sync-storage-persister": "^5.0.0-alpha.38", + "axios": "^1.4.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" }, "devDependencies": { - "@tanstack/eslint-plugin-query": "^4.13.0", - "@types/react": "^17.0.3", - "@types/react-dom": "^17.0.3", - "@vitejs/plugin-react": "^2.0.0", + "@tanstack/eslint-plugin-query": "^5.0.0-alpha.36", + "@types/react": "^18.2.4", + "@types/react-dom": "^18.2.4", + "@vitejs/plugin-react": "^4.0.0", "eslint": "^8.34.0", - "eslint-config-prettier": "^8.3.0", - "typescript": "4.7.4", - "vite": "^3.0.0" + "eslint-config-prettier": "^8.8.0", + "typescript": "^5.0.4", + "vite": "^4.2.0" }, "browserslist": { "production": [ diff --git a/examples/react/basic/package.json b/examples/react/basic/package.json index c61ce45c4b..d327469cda 100644 --- a/examples/react/basic/package.json +++ b/examples/react/basic/package.json @@ -8,16 +8,16 @@ "preview": "vite preview" }, "dependencies": { - "@tanstack/react-query": "^4.7.1", - "@tanstack/react-query-devtools": "^4.7.1", - "axios": "^0.21.1", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "@tanstack/react-query": "^5.0.0-alpha.38", + "@tanstack/react-query-devtools": "^5.0.0-alpha.38", + "axios": "^1.4.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" }, "devDependencies": { - "@tanstack/eslint-plugin-query": "^4.13.0", - "@vitejs/plugin-react": "^2.0.0", - "vite": "^3.0.0" + "@tanstack/eslint-plugin-query": "^5.0.0-alpha.36", + "@vitejs/plugin-react": "^4.0.0", + "vite": "^4.2.0" }, "browserslist": { "production": [ diff --git a/examples/react/default-query-function/package.json b/examples/react/default-query-function/package.json index e1d7be6c0b..dafb1d1e79 100644 --- a/examples/react/default-query-function/package.json +++ b/examples/react/default-query-function/package.json @@ -8,15 +8,15 @@ "preview": "vite preview" }, "dependencies": { - "axios": "^0.26.1", - "react": "^18.0.0", - "react-dom": "^18.0.0", - "@tanstack/react-query": "^4.7.1", - "@tanstack/react-query-devtools": "^4.7.1" + "axios": "^1.4.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "@tanstack/react-query": "^5.0.0-alpha.38", + "@tanstack/react-query-devtools": "^5.0.0-alpha.38" }, "devDependencies": { - "@vitejs/plugin-react": "^2.0.0", - "vite": "^3.0.0" + "@vitejs/plugin-react": "^4.0.0", + "vite": "^4.2.0" }, "browserslist": { "production": [ diff --git a/examples/react/infinite-query-with-max-pages/package.json b/examples/react/infinite-query-with-max-pages/package.json index b1d518e0cc..9ff7c67a6e 100644 --- a/examples/react/infinite-query-with-max-pages/package.json +++ b/examples/react/infinite-query-with-max-pages/package.json @@ -4,14 +4,14 @@ "main": "index.js", "license": "MIT", "dependencies": { - "axios": "^0.21.1", - "isomorphic-unfetch": "3.0.0", - "next": "12.2.2", + "@tanstack/react-query": "^5.0.0-alpha.38", + "@tanstack/react-query-devtools": "^5.0.0-alpha.38", + "axios": "^1.4.0", + "isomorphic-unfetch": "4.0.2", + "next": "^13.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-intersection-observer": "^8.33.1", - "@tanstack/react-query": "^4.7.1", - "@tanstack/react-query-devtools": "^4.7.1" + "react-intersection-observer": "^8.33.1" }, "scripts": { "dev": "next", diff --git a/examples/react/load-more-infinite-scroll/package.json b/examples/react/load-more-infinite-scroll/package.json index 5bcbe4c4cd..46cf041cda 100644 --- a/examples/react/load-more-infinite-scroll/package.json +++ b/examples/react/load-more-infinite-scroll/package.json @@ -4,14 +4,14 @@ "main": "index.js", "license": "MIT", "dependencies": { - "axios": "^0.21.1", - "isomorphic-unfetch": "3.0.0", - "next": "12.2.2", + "@tanstack/react-query": "^5.0.0-alpha.38", + "@tanstack/react-query-devtools": "^5.0.0-alpha.38", + "axios": "^1.4.0", + "isomorphic-unfetch": "4.0.2", + "next": "^13.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-intersection-observer": "^8.33.1", - "@tanstack/react-query": "^4.7.1", - "@tanstack/react-query-devtools": "^4.7.1" + "react-intersection-observer": "^8.33.1" }, "scripts": { "dev": "next", diff --git a/examples/react/load-more-infinite-scroll/pages/index.js b/examples/react/load-more-infinite-scroll/pages/index.js index 55280adaf4..782a3aa75f 100755 --- a/examples/react/load-more-infinite-scroll/pages/index.js +++ b/examples/react/load-more-infinite-scroll/pages/index.js @@ -48,7 +48,7 @@ function Example() { if (inView) { fetchNextPage() } - }, [inView]) + }, [fetchNextPage, inView]) return (
@@ -110,7 +110,7 @@ function Example() { )}
- Go to another page + Go to another page
diff --git a/examples/react/nextjs/components/Header/index.js b/examples/react/nextjs/components/Header/index.js index fdcb1dad06..cdd1d701a4 100644 --- a/examples/react/nextjs/components/Header/index.js +++ b/examples/react/nextjs/components/Header/index.js @@ -7,13 +7,11 @@ export const Header = () => { return (
- - Home + + Home - - - Client-Only - + + Client-Only