|
| 1 | +--- |
| 2 | +id: migrating-to-react-query-3 |
| 3 | +title: Migrating to React Query 3 |
| 4 | +--- |
| 5 | + |
| 6 | +## V3 migration |
| 7 | + |
| 8 | +This article explains how to migrate your application to React Query 3. |
| 9 | + |
| 10 | +### QueryClient |
| 11 | + |
| 12 | +The `QueryCache` has been split into a `QueryClient` and a `QueryCache`. |
| 13 | +The `QueryCache` contains all cached queries and the `QueryClient` can be used to interact with a cache. |
| 14 | + |
| 15 | +This has some benefits: |
| 16 | + |
| 17 | +- Allows for different type of caches. |
| 18 | +- Multiple clients with different configurations can use the same cache. |
| 19 | +- Clients can be used to track queries, which can be used for shared caches on SSR. |
| 20 | +- The client API is more focused towards general usage. |
| 21 | +- Easier to test the individual components. |
| 22 | + |
| 23 | +Use the `QueryClientProvider` component to connect a `QueryClient` to your application: |
| 24 | + |
| 25 | +```js |
| 26 | +import { QueryClient, QueryClientProvider, QueryCache } from 'react-query' |
| 27 | + |
| 28 | +const cache = new QueryCache() |
| 29 | +const client = new QueryClient({ cache }) |
| 30 | + |
| 31 | +function App() { |
| 32 | + return <QueryClientProvider client={client}>...</QueryClientProvider> |
| 33 | +} |
| 34 | +``` |
| 35 | + |
| 36 | +### useQueryCache() |
| 37 | + |
| 38 | +The `useQueryCache()` hook has been replaced by the `useQueryClient()` hook: |
| 39 | + |
| 40 | +```js |
| 41 | +import { useCallback } from 'react' |
| 42 | +import { useQueryClient } from 'react-query' |
| 43 | + |
| 44 | +function Todo() { |
| 45 | + const client = useQueryClient() |
| 46 | + |
| 47 | + const onClickButton = useCallback(() => { |
| 48 | + client.refetchQueries('posts') |
| 49 | + }, [client]) |
| 50 | + |
| 51 | + return <button onClick={onClickButton}>Refetch</button> |
| 52 | +} |
| 53 | +``` |
| 54 | + |
| 55 | +### ReactQueryConfigProvider |
| 56 | + |
| 57 | +The `ReactQueryConfigProvider` component has been removed. Default options for queries and mutations can now be specified in `QueryClient`: |
| 58 | + |
| 59 | +```js |
| 60 | +const client = new QueryClient({ |
| 61 | + cache, |
| 62 | + defaultOptions: { |
| 63 | + queries: { |
| 64 | + staleTime: Infinity, |
| 65 | + }, |
| 66 | + }, |
| 67 | +}) |
| 68 | +``` |
| 69 | + |
| 70 | +### usePaginatedQuery() |
| 71 | + |
| 72 | +The `usePaginatedQuery()` hook has been replaced by the `keepPreviousData` option on `useQuery`: |
| 73 | + |
| 74 | +```js |
| 75 | +import { useQuery } from 'react-query' |
| 76 | + |
| 77 | +function Page({ page }) { |
| 78 | + const { data } = useQuery(['page', page], fetchPage, { |
| 79 | + keepPreviousData: true, |
| 80 | + }) |
| 81 | +} |
| 82 | +``` |
| 83 | + |
| 84 | +### Query object syntax |
| 85 | + |
| 86 | +The object syntax has been collapsed: |
| 87 | + |
| 88 | +```js |
| 89 | +// Old: |
| 90 | +useQuery({ |
| 91 | + queryKey: 'posts', |
| 92 | + queryFn: fetchPosts, |
| 93 | + config: { staleTime: Infinity }, |
| 94 | +}) |
| 95 | + |
| 96 | +// New: |
| 97 | +useQuery({ |
| 98 | + queryKey: 'posts', |
| 99 | + queryFn: fetchPosts, |
| 100 | + staleTime: Infinity, |
| 101 | +}) |
| 102 | +``` |
| 103 | + |
| 104 | +### queryCache.invalidateQueries() |
| 105 | + |
| 106 | +The `client.invalidateQueries()` method will now only invalidate queries. |
| 107 | +All matched queries will be marked invalid and refetched on window focus, reconnect or mounting of components. |
| 108 | +Use `client.refetchQueries()` to refetch queries immediately. |
| 109 | + |
| 110 | +### queryCache.refetchQueries() |
| 111 | + |
| 112 | +The `client.refetchQueries()` method can be used to refetch queries like the `refetch()` method. |
| 113 | +By default it will only refetch active queries, but an `inactive` flag can be set to also refetch inactive queries. |
| 114 | + |
| 115 | +```js |
| 116 | +// Refetch all active queries: |
| 117 | +client.refetchQueries() |
| 118 | + |
| 119 | +// Also refetch inactive queries: |
| 120 | +client.refetchQueries({ inactive: true }) |
| 121 | + |
| 122 | +// Fetch active queries matching a query key: |
| 123 | +client.refetchQueries('posts') |
| 124 | + |
| 125 | +// Also fetch inactive queries: |
| 126 | +client.refetchQueries('posts', { inactive: true }) |
| 127 | + |
| 128 | +// Only fetch inactive queries: |
| 129 | +client.refetchQueries('posts', { active: false, inactive: true }) |
| 130 | +``` |
| 131 | + |
| 132 | +The same filters can be used in the `client.cancelQueries()`, `client.invalidateQueries()` and `client.removeQueries()` methods but these methods will include all queries by default. |
| 133 | + |
| 134 | +### queryCache.prefetchQuery() |
| 135 | + |
| 136 | +The `client.prefetchQuery()` method should now only be used for prefetching scenarios where the result is not relevant. |
| 137 | + |
| 138 | +Use the `client.fetchQueryData()` method to get the query data or error: |
| 139 | + |
| 140 | +```js |
| 141 | +// Prefetch a query: |
| 142 | +await client.prefetchQuery('posts', fetchPosts) |
| 143 | + |
| 144 | +// Fetch a query: |
| 145 | +try { |
| 146 | + const data = await client.fetchQueryData('posts', fetchPosts) |
| 147 | +} catch (error) { |
| 148 | + // Error handling |
| 149 | +} |
| 150 | +``` |
| 151 | + |
| 152 | +### ReactQueryCacheProvider |
| 153 | + |
| 154 | +The `ReactQueryCacheProvider` component has been replaced by the `QueryClientProvider` component. |
| 155 | + |
| 156 | +### makeQueryCache() |
| 157 | + |
| 158 | +The `makeQueryCache()` function has replaced by `new QueryCache()`. |
| 159 | + |
| 160 | +### ReactQueryErrorResetBoundary |
| 161 | + |
| 162 | +The `ReactQueryErrorResetBoundary` component has been renamed to `QueryErrorResetBoundary`. |
| 163 | + |
| 164 | +### queryCache.resetErrorBoundaries() |
| 165 | + |
| 166 | +The `queryCache.resetErrorBoundaries()` method has been replaced by the `QueryErrorResetBoundary` component. |
| 167 | + |
| 168 | +### queryCache.getQuery() |
| 169 | + |
| 170 | +The `queryCache.getQuery()` method has been replaced by `cache.find()`. |
| 171 | + |
| 172 | +### queryCache.getQueries() |
| 173 | + |
| 174 | +The `queryCache.getQueries()` method has been replaced by `cache.findAll()`. |
| 175 | + |
| 176 | +### queryCache.isFetching |
| 177 | + |
| 178 | +The `queryCache.isFetching` property has been replaced by `client.isFetching()`. |
| 179 | + |
| 180 | +### QueryOptions.initialStale |
| 181 | + |
| 182 | +The `initialStale` query option has been removed and initial data is now treated as regular data. |
| 183 | +Which means that if `initialData` is provided, the query will refetch on mount by default. |
| 184 | +If you do not want to refetch immediately, you can define a `staleTime`. |
| 185 | + |
| 186 | +### QueryOptions.forceFetchOnMount |
| 187 | + |
| 188 | +The `forceFetchOnMount` query option has been replaced by `refetchOnMount: 'always'`. |
| 189 | + |
| 190 | +### QueryOptions.refetchOnMount |
| 191 | + |
| 192 | +When `refetchOnMount` was set to `false` any additional components were prevented from refetching on mount. |
| 193 | +In version 3 only the component where the option has been set will not refetch on mount. |
| 194 | + |
| 195 | +### QueryResult.clear() |
| 196 | + |
| 197 | +The `QueryResult.clear()` method has been renamed to `QueryResult.remove()`. |
| 198 | + |
| 199 | +### New features |
| 200 | + |
| 201 | +Some new features have also been added besides the API changes, performance improvements and file size reduction. |
| 202 | + |
| 203 | +#### Selectors |
| 204 | + |
| 205 | +The `useQuery` and `useInfiniteQuery` hooks now have a `select` option to select or transform parts of the query result. |
| 206 | + |
| 207 | +```js |
| 208 | +import { useQuery } from 'react-query' |
| 209 | + |
| 210 | +function User() { |
| 211 | + const { data } = useQuery('user', fetchUser, { |
| 212 | + select: user => user.username, |
| 213 | + }) |
| 214 | + return <div>Username: {data}</div> |
| 215 | +} |
| 216 | +``` |
| 217 | + |
| 218 | +Set the `notifyOnStatusChange` option to `false` to only re-render when the selected data changes. |
| 219 | + |
| 220 | +#### useQueries() |
| 221 | + |
| 222 | +The `useQueries()` hook can be used to fetch a variable number of queries: |
| 223 | + |
| 224 | +```js |
| 225 | +import { useQueries } from 'react-query' |
| 226 | + |
| 227 | +function Overview() { |
| 228 | + const results = useQueries([ |
| 229 | + { queryKey: ['post', 1], queryFn: fetchPost }, |
| 230 | + { queryKey: ['post', 2], queryFn: fetchPost }, |
| 231 | + ]) |
| 232 | + return ( |
| 233 | + <ul> |
| 234 | + {results.map(({ data }) => data && <li key={data.id}>{data.title})</li>)} |
| 235 | + </ul> |
| 236 | + ) |
| 237 | +} |
| 238 | +``` |
| 239 | + |
| 240 | +#### client.watchQuery() |
| 241 | + |
| 242 | +The `client.watchQuery()` method can be used to create and/or watch a query: |
| 243 | + |
| 244 | +```js |
| 245 | +const observer = client.watchQuery('posts') |
| 246 | + |
| 247 | +observer.subscribe(result => { |
| 248 | + console.log(result) |
| 249 | + observer.unsubscribe() |
| 250 | +}) |
| 251 | +``` |
| 252 | + |
| 253 | +#### client.watchQueries() |
| 254 | + |
| 255 | +The `client.watchQueries()` method can be used to create and/or watch multiple queries: |
| 256 | + |
| 257 | +```js |
| 258 | +const observer = client.watchQueries([ |
| 259 | + { queryKey: ['post', 1], queryFn: fetchPost }, |
| 260 | + { queryKey: ['post', 2], queryFn: fetchPost }, |
| 261 | +]) |
| 262 | + |
| 263 | +observer.subscribe(result => { |
| 264 | + console.log(result) |
| 265 | + observer.unsubscribe() |
| 266 | +}) |
| 267 | +``` |
| 268 | + |
| 269 | +#### React Native error screens |
| 270 | + |
| 271 | +To prevent showing error screens in React Native when a query fails it was necessary to manually change the Console: |
| 272 | + |
| 273 | +```js |
| 274 | +import { setConsole } from 'react-query' |
| 275 | + |
| 276 | +setConsole({ |
| 277 | + log: console.log, |
| 278 | + warn: console.warn, |
| 279 | + error: console.warn, |
| 280 | +}) |
| 281 | +``` |
| 282 | + |
| 283 | +In version 3 this is done automatically when React Query is used in React Native. |
0 commit comments