diff --git a/docs/framework/react/guides/migrating-to-react-query-3.md b/docs/framework/react/guides/migrating-to-react-query-3.md index d1d9ce48c1b..e41a441bc63 100644 --- a/docs/framework/react/guides/migrating-to-react-query-3.md +++ b/docs/framework/react/guides/migrating-to-react-query-3.md @@ -425,19 +425,19 @@ Therefore you have to change the enum properties to their equivalent string lite Here is an example of the changes you would have to make: -```diff -- import { useQuery, QueryStatus } from 'react-query'; -+ import { useQuery } from 'react-query'; +```tsx +- import { useQuery, QueryStatus } from 'react-query'; // [!code --] ++ import { useQuery } from 'react-query'; // [!code ++] const { data, status } = useQuery(['post', id], () => fetchPost(id)) -- if (status === QueryStatus.Loading) { -+ if (status === 'loading') { +- if (status === QueryStatus.Loading) { // [!code --] ++ if (status === 'loading') { // [!code ++] ... } -- if (status === QueryStatus.Error) { -+ if (status === 'error') { +- if (status === QueryStatus.Error) { // [!code --] ++ if (status === 'error') { // [!code ++] ... } ``` diff --git a/docs/framework/react/guides/migrating-to-react-query-4.md b/docs/framework/react/guides/migrating-to-react-query-4.md index dc4bc988fa1..23a5ba12b1e 100644 --- a/docs/framework/react/guides/migrating-to-react-query-4.md +++ b/docs/framework/react/guides/migrating-to-react-query-4.md @@ -17,12 +17,12 @@ npm install @tanstack/react-query npm install @tanstack/react-query-devtools ``` -```diff -- import { useQuery } from 'react-query' -- import { ReactQueryDevtools } from 'react-query/devtools' +```tsx +- import { useQuery } from 'react-query' // [!code --] +- import { ReactQueryDevtools } from 'react-query/devtools' // [!code --] -+ import { useQuery } from '@tanstack/react-query' -+ import { ReactQueryDevtools } from '@tanstack/react-query-devtools' ++ import { useQuery } from '@tanstack/react-query' // [!code ++] ++ import { ReactQueryDevtools } from '@tanstack/react-query-devtools' // [!code ++] ``` #### Codemod @@ -64,9 +64,9 @@ However, we have not followed this concept through to all apis. For example, whe To streamline all apis, we've decided to make all keys Arrays only: -```diff -- useQuery('todos', fetchTodos) -+ useQuery(['todos'], fetchTodos) +```tsx +- useQuery('todos', fetchTodos) // [!code --] ++ useQuery(['todos'], fetchTodos) // [!code ++] ``` #### Codemod @@ -104,10 +104,10 @@ With the introduction of the new [fetchStatus](../queries#fetchstatus) for bette This will mostly affect `disabled` queries that don't have any `data` yet, as those were in `idle` state before: -```diff -- status: 'idle' -+ status: 'loading' -+ fetchStatus: 'idle' +```tsx +- status: 'idle' // [!code --] ++ status: 'loading' // [!code ++] ++ fetchStatus: 'idle' // [!code ++] ``` Also, have a look at [the guide on dependent queries](../dependent-queries) @@ -116,9 +116,9 @@ Also, have a look at [the guide on dependent queries](../dependent-queries) Due to this change, disabled queries (even temporarily disabled ones) will start in `loading` state. To make migration easier, especially for having a good flag to know when to display a loading spinner, you can check for `isInitialLoading` instead of `isLoading`: -```diff -- isLoading -+ isInitialLoading +```tsx +- isLoading // [!code --] ++ isInitialLoading // [!code ++] ``` See also the guide on [disabling queries](../disabling-queries#isInitialLoading) @@ -127,9 +127,9 @@ See also the guide on [disabling queries](../disabling-queries#isInitialLoading) The `useQueries` hook now accepts an object with a `queries` prop as its input. The value of the `queries` prop is an array of queries (this array is identical to what was passed into `useQueries` in v3). -```diff -- useQueries([{ queryKey1, queryFn1, options1 }, { queryKey2, queryFn2, options2 }]) -+ useQueries({ queries: [{ queryKey1, queryFn1, options1 }, { queryKey2, queryFn2, options2 }] }) +```tsx +- useQueries([{ queryKey1, queryFn1, options1 }, { queryKey2, queryFn2, options2 }]) // [!code --] ++ useQueries({ queries: [{ queryKey1, queryFn1, options1 }, { queryKey2, queryFn2, options2 }] }) // [!code ++] ``` ### Undefined is an illegal cache value for successful queries @@ -224,10 +224,10 @@ Those flags don't work well when used together, because they are mutually exclus With v4, those filters have been combined into a single filter to better show the intent: -```diff -- active?: boolean -- inactive?: boolean -+ type?: 'active' | 'inactive' | 'all' +```tsx +- active?: boolean // [!code --] +- inactive?: boolean // [!code --] ++ type?: 'active' | 'inactive' | 'all' // [!code ++] ``` The filter defaults to `all`, and you can choose to only match `active` or `inactive` queries. @@ -249,10 +249,10 @@ refetchInactive: Boolean For the same reason, those have also been combined: -```diff -- refetchActive?: boolean -- refetchInactive?: boolean -+ refetchType?: 'active' | 'inactive' | 'all' | 'none' +```tsx +- refetchActive?: boolean // [!code --] +- refetchInactive?: boolean // [!code --] ++ refetchType?: 'active' | 'inactive' | 'all' | 'none' // [!code ++] ``` This flag defaults to `active` because `refetchActive` defaulted to `true`. This means we also need a way to tell `invalidateQueries` to not refetch at all, which is why a fourth option (`none`) is also allowed here. @@ -276,14 +276,14 @@ The plugins `createWebStoragePersistor` and `createAsyncStoragePersistor` have b Since these plugins are no longer experimental, their import paths have also been updated: -```diff -- import { persistQueryClient } from 'react-query/persistQueryClient-experimental' -- import { createWebStoragePersistor } from 'react-query/createWebStoragePersistor-experimental' -- import { createAsyncStoragePersistor } from 'react-query/createAsyncStoragePersistor-experimental' +```tsx +- import { persistQueryClient } from 'react-query/persistQueryClient-experimental' // [!code --] +- import { createWebStoragePersistor } from 'react-query/createWebStoragePersistor-experimental' // [!code --] +- import { createAsyncStoragePersistor } from 'react-query/createAsyncStoragePersistor-experimental' // [!code --] -+ import { persistQueryClient } from '@tanstack/react-query-persist-client' -+ import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister' -+ import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister' ++ import { persistQueryClient } from '@tanstack/react-query-persist-client' // [!code ++] ++ import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister' // [!code ++] ++ import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister' // [!code ++] ``` ### The `cancel` method on promises is no longer supported @@ -302,13 +302,13 @@ As of v4, React Query is optimized for modern browsers. We have updated our brow It was possible to change the logger globally by calling `setLogger`. In v4, that function is replaced with an optional field when creating a `QueryClient`. -```diff -- import { QueryClient, setLogger } from 'react-query'; -+ import { QueryClient } from '@tanstack/react-query'; +```tsx +- import { QueryClient, setLogger } from 'react-query'; // [!code --] ++ import { QueryClient } from '@tanstack/react-query'; // [!code ++] -- setLogger(customLogger) -- const queryClient = new QueryClient(); -+ const queryClient = new QueryClient({ logger: customLogger }) +- setLogger(customLogger) // [!code --] +- const queryClient = new QueryClient(); // [!code --] ++ const queryClient = new QueryClient({ logger: customLogger }) // [!code ++] ``` ### No _default_ manual Garbage Collection server-side @@ -334,13 +334,13 @@ Subscribing manually to the `QueryCache` has always given you a `QueryCacheNotif #### QueryCacheNotifyEvent -```diff -- type: 'queryAdded' -+ type: 'added' -- type: 'queryRemoved' -+ type: 'removed' -- type: 'queryUpdated' -+ type: 'updated' +```tsx +- type: 'queryAdded' // [!code --] ++ type: 'added' // [!code ++] +- type: 'queryRemoved' // [!code --] ++ type: 'removed' // [!code ++] +- type: 'queryUpdated' // [!code --] ++ type: 'updated' // [!code ++] ``` #### MutationCacheNotifyEvent @@ -353,26 +353,26 @@ The `MutationCacheNotifyEvent` uses the same types as the `QueryCacheNotifyEvent With version [3.22.0](https://github.com/tannerlinsley/react-query/releases/tag/v3.22.0), hydration utilities moved into the React Query core. With v3, you could still use the old exports from `react-query/hydration`, but these exports have been removed with v4. -```diff -- import { dehydrate, hydrate, useHydrate, Hydrate } from 'react-query/hydration' -+ import { dehydrate, hydrate, useHydrate, Hydrate } from '@tanstack/react-query' +```tsx +- import { dehydrate, hydrate, useHydrate, Hydrate } from 'react-query/hydration' // [!code --] ++ import { dehydrate, hydrate, useHydrate, Hydrate } from '@tanstack/react-query' // [!code ++] ``` ### Removed undocumented methods from the `queryClient`, `query` and `mutation` The methods `cancelMutatations` and `executeMutation` on the `QueryClient` were undocumented and unused internally, so we removed them. Since it was just a wrapper around a method available on the `mutationCache`, you can still use the functionality of `executeMutation` -```diff -- executeMutation< -- TData = unknown, -- TError = unknown, -- TVariables = void, -- TContext = unknown -- >( -- options: MutationOptions -- ): Promise { -- return this.mutationCache.build(this, options).execute() -- } +```tsx +- executeMutation< // [!code --] +- TData = unknown, // [!code --] +- TError = unknown, // [!code --] +- TVariables = void, // [!code --] +- TContext = unknown // [!code --] +- >( // [!code --] +- options: MutationOptions // [!code --] +- ): Promise { // [!code --] +- return this.mutationCache.build(this, options).execute() // [!code --] +- } // [!code --] ``` Additionally, `query.setDefaultOptions` was removed because it was also unused. `mutation.cancel` was removed because it didn't actually cancel the outgoing request. @@ -389,9 +389,9 @@ With the renamed directory this no longer is an issue. If you were importing anything from `'react-query/react'` directly in your project (as opposed to just `'react-query'`), then you need to update your imports: -```diff -- import { QueryClientProvider } from 'react-query/react'; -+ import { QueryClientProvider } from '@tanstack/react-query/reactjs'; +```tsx +- import { QueryClientProvider } from 'react-query/react'; // [!code --] ++ import { QueryClientProvider } from '@tanstack/react-query/reactjs'; // [!code ++] ``` ## New Features 🚀 diff --git a/docs/framework/react/guides/migrating-to-v5.md b/docs/framework/react/guides/migrating-to-v5.md index 5fd686c2508..1c8a1175123 100644 --- a/docs/framework/react/guides/migrating-to-v5.md +++ b/docs/framework/react/guides/migrating-to-v5.md @@ -13,88 +13,88 @@ useQuery and friends used to have many overloads in TypeScript - different ways now we only support the object format. -```diff -- useQuery(key, fn, options) -+ useQuery({ queryKey, queryFn, ...options }) +```tsx +- useQuery(key, fn, options) // [!code --] ++ useQuery({ queryKey, queryFn, ...options }) // [!code ++] -- useInfiniteQuery(key, fn, options) -+ useInfiniteQuery({ queryKey, queryFn, ...options }) +- useInfiniteQuery(key, fn, options) // [!code --] ++ useInfiniteQuery({ queryKey, queryFn, ...options }) // [!code ++] -- useMutation(fn, options) -+ useMutation({ mutationFn, ...options }) +- useMutation(fn, options) // [!code --] ++ useMutation({ mutationFn, ...options }) // [!code ++] -- useIsFetching(key, filters) -+ useIsFetching({ queryKey, ...filters }) +- useIsFetching(key, filters) // [!code --] ++ useIsFetching({ queryKey, ...filters }) // [!code ++] -- useIsMutating(key, filters) -+ useIsMutating({ mutationKey, ...filters }) +- useIsMutating(key, filters) // [!code --] ++ useIsMutating({ mutationKey, ...filters }) // [!code ++] ``` -```diff -- queryClient.isFetching(key, filters) -+ queryClient.isFetching({ queryKey, ...filters }) +```tsx +- queryClient.isFetching(key, filters) // [!code --] ++ queryClient.isFetching({ queryKey, ...filters }) // [!code ++] -- queryClient.ensureQueryData(key, filters) -+ queryClient.ensureQueryData({ queryKey, ...filters }) +- queryClient.ensureQueryData(key, filters) // [!code --] ++ queryClient.ensureQueryData({ queryKey, ...filters }) // [!code ++] -- queryClient.getQueriesData(key, filters) -+ queryClient.getQueriesData({ queryKey, ...filters }) +- queryClient.getQueriesData(key, filters) // [!code --] ++ queryClient.getQueriesData({ queryKey, ...filters }) // [!code ++] -- queryClient.setQueriesData(key, updater, filters, options) -+ queryClient.setQueriesData({ queryKey, ...filters }, updater, options) +- queryClient.setQueriesData(key, updater, filters, options) // [!code --] ++ queryClient.setQueriesData({ queryKey, ...filters }, updater, options) // [!code ++] -- queryClient.removeQueries(key, filters) -+ queryClient.removeQueries({ queryKey, ...filters }) +- queryClient.removeQueries(key, filters) // [!code --] ++ queryClient.removeQueries({ queryKey, ...filters }) // [!code ++] -- queryClient.resetQueries(key, filters, options) -+ queryClient.resetQueries({ queryKey, ...filters }, options) +- queryClient.resetQueries(key, filters, options) // [!code --] ++ queryClient.resetQueries({ queryKey, ...filters }, options) // [!code ++] -- queryClient.cancelQueries(key, filters, options) -+ queryClient.cancelQueries({ queryKey, ...filters }, options) +- queryClient.cancelQueries(key, filters, options) // [!code --] ++ queryClient.cancelQueries({ queryKey, ...filters }, options) // [!code ++] -- queryClient.invalidateQueries(key, filters, options) -+ queryClient.invalidateQueries({ queryKey, ...filters }, options) +- queryClient.invalidateQueries(key, filters, options) // [!code --] ++ queryClient.invalidateQueries({ queryKey, ...filters }, options) // [!code ++] -- queryClient.refetchQueries(key, filters, options) -+ queryClient.refetchQueries({ queryKey, ...filters }, options) +- queryClient.refetchQueries(key, filters, options) // [!code --] ++ queryClient.refetchQueries({ queryKey, ...filters }, options) // [!code ++] -- queryClient.fetchQuery(key, fn, options) -+ queryClient.fetchQuery({ queryKey, queryFn, ...options }) +- queryClient.fetchQuery(key, fn, options) // [!code --] ++ queryClient.fetchQuery({ queryKey, queryFn, ...options }) // [!code ++] -- queryClient.prefetchQuery(key, fn, options) -+ queryClient.prefetchQuery({ queryKey, queryFn, ...options }) +- queryClient.prefetchQuery(key, fn, options) // [!code --] ++ queryClient.prefetchQuery({ queryKey, queryFn, ...options }) // [!code ++] -- queryClient.fetchInfiniteQuery(key, fn, options) -+ queryClient.fetchInfiniteQuery({ queryKey, queryFn, ...options }) +- queryClient.fetchInfiniteQuery(key, fn, options) // [!code --] ++ queryClient.fetchInfiniteQuery({ queryKey, queryFn, ...options }) // [!code ++] -- queryClient.prefetchInfiniteQuery(key, fn, options) -+ queryClient.prefetchInfiniteQuery({ queryKey, queryFn, ...options }) +- queryClient.prefetchInfiniteQuery(key, fn, options) // [!code --] ++ queryClient.prefetchInfiniteQuery({ queryKey, queryFn, ...options }) // [!code ++] ``` -```diff -- queryCache.find(key, filters) -+ queryCache.find({ queryKey, ...filters }) +```tsx +- queryCache.find(key, filters) // [!code --] ++ queryCache.find({ queryKey, ...filters }) // [!code ++] -- queryCache.findAll(key, filters) -+ queryCache.findAll({ queryKey, ...filters }) +- queryCache.findAll(key, filters) // [!code --] ++ queryCache.findAll({ queryKey, ...filters }) // [!code ++] ``` ### `queryClient.getQueryData` now accepts queryKey only as an Argument `queryClient.getQueryData` argument is changed to accept only a `queryKey` -```diff -- queryClient.getQueryData(queryKey, filters) -+ queryClient.getQueryData(queryKey) +```tsx +- queryClient.getQueryData(queryKey, filters) // [!code --] ++ queryClient.getQueryData(queryKey) // [!code ++] ``` ### `queryClient.getQueryState` now accepts queryKey only as an Argument `queryClient.getQueryState` argument is changed to accept only a `queryKey` -```diff -- queryClient.getQueryState(queryKey, filters) -+ queryClient.getQueryState(queryKey) +```tsx +- queryClient.getQueryState(queryKey, filters) // [!code --] ++ queryClient.getQueryState(queryKey) // [!code ++] ``` #### Codemod @@ -140,9 +140,9 @@ A few notes about how codemod works: This streamlines how callbacks are invoked (the `refetchOnWindowFocus`, `refetchOnMount` and `refetchOnReconnect` callbacks all only get the query passed as well), and it fixes some typing issues when callbacks get data transformed by `select`. -```diff -- refetchInterval: number | false | ((data: TData | undefined, query: Query) => number | false | undefined) -+ refetchInterval: number | false | ((query: Query) => number | false | undefined) +```tsx +- refetchInterval: number | false | ((data: TData | undefined, query: Query) => number | false | undefined) // [!code --] ++ refetchInterval: number | false | ((query: Query) => number | false | undefined) // [!code ++] ``` You can still access data with `query.state.data`, however, it will not be data that has been transformed by `select`. If you need to access the transformed data, you can call the transformation again on `query.state.data`. @@ -155,12 +155,12 @@ But It doesn't make much sense to do this while a query is still active, because if you still need to remove a query, you can use `queryClient.removeQueries({queryKey: key})` -```diff +```tsx const queryClient = useQueryClient(); const query = useQuery({ queryKey, queryFn }); -- query.remove() -+ queryClient.removeQueries({ queryKey }) +- query.remove() // [!code --] ++ queryClient.removeQueries({ queryKey }) // [!code ++] ``` ### The minimum required TypeScript version is now 4.7 @@ -173,11 +173,11 @@ Previously, This function was used to indicate whether to use previous `data` (` You can achieve the same functionality by passing a function to `structuralSharing` instead: -```diff +```tsx import { replaceEqualDeep } from '@tanstack/react-query' -- isDataEqual: (oldData, newData) => customCheck(oldData, newData) -+ structuralSharing: (oldData, newData) => customCheck(oldData, newData) ? oldData : replaceEqualDeep(oldData, newData) +- isDataEqual: (oldData, newData) => customCheck(oldData, newData) // [!code --] ++ structuralSharing: (oldData, newData) => customCheck(oldData, newData) ? oldData : replaceEqualDeep(oldData, newData) // [!code ++] ``` ### The deprecated custom logger has been removed @@ -200,14 +200,14 @@ Almost everyone gets `cacheTime` wrong. It sounds like "the amount of time that `gc` is referring to "garbage collect" time. It's a bit more technical, but also a quite [well known abbreviation]() in computer science. -```diff +```tsx const MINUTE = 1000 * 60; const queryClient = new QueryClient({ defaultOptions: { queries: { -- cacheTime: 10 * MINUTE, -+ gcTime: 10 * MINUTE, +- cacheTime: 10 * MINUTE, // [!code --] ++ gcTime: 10 * MINUTE, // [!code ++] }, }, }) @@ -249,21 +249,21 @@ To achieve the same functionality as `keepPreviousData`, we have added previous > A note here is that `useQueries` would not receive `previousData` in the `placeholderData` function as argument. This is due to a dynamic nature of queries passed in the array, which may lead to a different shape of result from placeholder and queryFn. -```diff +```tsx import { useQuery, -+ keepPreviousData ++ keepPreviousData // [!code ++] } from "@tanstack/react-query"; const { data, -- isPreviousData, -+ isPlaceholderData, +- isPreviousData, // [!code --] ++ isPlaceholderData, // [!code ++] } = useQuery({ queryKey, queryFn, -- keepPreviousData: true, -+ placeholderData: keepPreviousData +- keepPreviousData: true, // [!code --] ++ placeholderData: keepPreviousData // [!code ++] }); ``` @@ -316,16 +316,16 @@ In v4, we introduced the possibility to pass a custom `context` to all react-que However, `context` is a react-only feature. All that `context` does is give us access to the `queryClient`. We could achieve the same isolation by allowing to pass in a custom `queryClient` directly. This in turn will enable other frameworks to have the same functionality in a framework-agnostic way. -```diff +```tsx import { queryClient } from './my-client' const { data } = useQuery( { queryKey: ['users', id], queryFn: () => fetch(...), -- context: customContext +- context: customContext // [!code --] }, -+ queryClient, ++ queryClient, // [!code ++] ) ``` @@ -341,9 +341,9 @@ The v5 includes a new `maxPages` option for infinite queries to limit the number The options you can pass to `dehydrate` have been simplified. Queries and Mutations are always dehydrated (according to the default function implementation). To change this behaviour, instead of using the removed boolean options `dehydrateMutations` and `dehydrateQueries` you can implement the function equivalents `shouldDehydrateQuery` or `shouldDehydrateMutation` instead. To get the old behaviour of not hydrating queries/mutations at all, pass in `() => false`. -```diff -- dehydrateMutations?: boolean -- dehydrateQueries?: boolean +```tsx +- dehydrateMutations?: boolean // [!code --] +- dehydrateQueries?: boolean // [!code --] ``` ### Infinite queries now need a `initialPageParam` @@ -352,12 +352,12 @@ Previously, we've passed `undefined` to the `queryFn` as `pageParam`, and you co Instead, you now have to pass an explicit `initialPageParam` to the infinite query options. This will be used as the `pageParam` for the first page: -```diff +```tsx useInfiniteQuery({ queryKey, -- queryFn: ({ pageParam = 0 }) => fetchSomething(pageParam), -+ queryFn: ({ pageParam }) => fetchSomething(pageParam), -+ initialPageParam: 0, +- queryFn: ({ pageParam = 0 }) => fetchSomething(pageParam), // [!code --] ++ queryFn: ({ pageParam }) => fetchSomething(pageParam), // [!code ++] ++ initialPageParam: 0, // [!code ++] getNextPageParam: (lastPage) => lastPage.next, }) ``` @@ -425,16 +425,16 @@ Finally, as a technical detail, the timing for when queries are hydrated have ch This last change is technically a breaking one, and was made so we don't prematurely update content on the _existing_ page before a page transition has been fully committed. No action is required on your part. -```diff -- import { Hydrate } from '@tanstack/react-query' -+ import { HydrationBoundary } from '@tanstack/react-query' +```tsx +- import { Hydrate } from '@tanstack/react-query' // [!code --] ++ import { HydrationBoundary } from '@tanstack/react-query' // [!code ++] -- -+ +- // [!code --] ++ // [!code ++] -- -+ +- // [!code --] ++ // [!code ++] ``` [//]: # 'FrameworkSpecificBreakingChanges'