
This article explains how to migrate your application to React Query 3.
The QueryCache has been split into a QueryClient and a QueryCache.
The QueryCache contains all cached queries and the QueryClient can be used to interact with a cache.
This has some benefits:
Use the QueryClientProvider component to connect a QueryClient to your application:
import { QueryClient, QueryClientProvider, QueryCache } from 'react-query'const cache = new QueryCache()const client = new QueryClient({ cache })function App() {return <QueryClientProvider client={client}>...</QueryClientProvider>}
The useQueryCache() hook has been replaced by the useQueryClient() hook:
import { useCallback } from 'react'import { useQueryClient } from 'react-query'function Todo() {const client = useQueryClient()const onClickButton = useCallback(() => {client.invalidateQueries('posts')}, [client])return <button onClick={onClickButton}>Refetch</button>}
The ReactQueryConfigProvider component has been removed. Default options for queries and mutations can now be specified in QueryClient:
const client = new QueryClient({cache,defaultOptions: {queries: {staleTime: Infinity,},},})
The usePaginatedQuery() hook has been replaced by the keepPreviousData option on useQuery:
import { useQuery } from 'react-query'function Page({ page }) {const { data } = useQuery(['page', page], fetchPage, {keepPreviousData: true,})}
The object syntax has been collapsed:
// Old:useQuery({queryKey: 'posts',queryFn: fetchPosts,config: { staleTime: Infinity },})// New:useQuery({queryKey: 'posts',queryFn: fetchPosts,staleTime: Infinity,})
The client.prefetchQuery() method should now only be used for prefetching scenarios where the result is not relevant.
Use the client.fetchQueryData() method to get the query data or error:
// Prefetch a query:await client.prefetchQuery('posts', fetchPosts)// Fetch a query:try {const data = await client.fetchQueryData('posts', fetchPosts)} catch (error) {// Error handling}
The ReactQueryCacheProvider component has been replaced by the QueryClientProvider component.
The makeQueryCache() function has replaced by new QueryCache().
The ReactQueryErrorResetBoundary component has been renamed to QueryErrorResetBoundary.
The queryCache.resetErrorBoundaries() method has been replaced by the QueryErrorResetBoundary component.
The queryCache.getQuery() method has been replaced by cache.find().
The queryCache.getQueries() method has been replaced by cache.findAll().
The queryCache.isFetching property has been replaced by client.isFetching().
The enabled query option will now only disable a query when the value is false.
If needed, values can be casted with !!userId or Boolean(userId).
The initialStale query option has been removed and initial data is now treated as regular data.
Which means that if initialData is provided, the query will refetch on mount by default.
If you do not want to refetch immediately, you can define a staleTime.
The forceFetchOnMount query option has been replaced by refetchOnMount: 'always'.
When refetchOnMount was set to false any additional components were prevented from refetching on mount.
In version 3 only the component where the option has been set will not refetch on mount.
The QueryResult.clear() method has been renamed to QueryResult.remove().
The setConsole function has been replaced by setLogger:
import { setLogger } from 'react-query'// Log with SentrysetLogger({error: error => {Sentry.captureException(error)},})// Log with WinstonsetLogger(winston.createLogger())
To prevent showing error screens in React Native when a query fails it was necessary to manually change the Console:
import { setConsole } from 'react-query'setConsole({log: console.log,warn: console.warn,error: console.warn,})
In version 3 this is done automatically when React Query is used in React Native.
Some new features have also been added besides the API changes, performance improvements and file size reduction.
The useQuery and useInfiniteQuery hooks now have a select option to select or transform parts of the query result.
import { useQuery } from 'react-query'function User() {const { data } = useQuery('user', fetchUser, {select: user => user.username,})return <div>Username: {data}</div>}
Set the notifyOnStatusChange option to false to only re-render when the selected data changes.
The useQueries() hook can be used to fetch a variable number of queries:
import { useQueries } from 'react-query'function Overview() {const results = useQueries([{ queryKey: ['post', 1], queryFn: fetchPost },{ queryKey: ['post', 2], queryFn: fetchPost },])return (<ul>{results.map(({ data }) => data && <li key={data.id}>{data.title})</li>)}</ul>)}
The client.watchQuery() method can be used to create and/or watch a query:
const observer = client.watchQuery('posts')const unsubscribe = observer.subscribe(result => {console.log(result)unsubscribe()})
The client.watchQueries() method can be used to create and/or watch multiple queries:
const observer = client.watchQueries([{ queryKey: ['post', 1], queryFn: fetchPost },{ queryKey: ['post', 2], queryFn: fetchPost },])const unsubscribe = observer.subscribe(result => {console.log(result)unsubscribe()})
client.setQueryDefaultsThe client.setQueryDefaults() method to set default options for a specific query. If the query does not exist yet it will create it.
client.setQueryDefaults('posts', fetchPosts)function Component() {const { data } = useQuery('posts')}
The useIsFetching() hook now accepts filters which can be used to for example only show a spinner for certain type of queries:
const fetches = useIsFetching(['posts'])
The core of React Query is now fully separated from React, which means it can also be used standalone or in other frameworks. Use the react-query/core entrypoint to only import the core functionality:
import { QueryClient } from 'react-query/core'
The latest TanStack news, articles, and resources, sent to your inbox.