🤖 Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.
MIT License
Bot releases are hidden (Show)
Published by tannerlinsley over 4 years ago
idle
query stateTYPESCRIPT USERS! Types are currently being updated to use the new 2.0 api and will be available very soon. You can make that happen faster by contributing to them in
/types/index.d.ts
and testing them in/types/test.ts
and opening a PR!
Do you use falsy query keys for dependent queries?
enabled
config flag. You should move your conditions in your key to the enabled
option
useQuery(ready && queryKey, queryFn)
useQuery(queryKey, queryFn, { enabled: ready })
Do you use functions as queryKeys for dependent queries?
enabled
config option and use optional chaining to cast them to a boolean
useQuery(() => ['user', user.id], queryFn)
useQuery(['user', user?.id], queryFn, { enabled: user?.id })
Do you expect dependent queries to start in the success
state?
Dependent queries now start in a new idle
state. You should account for this new state where possible. Most rendering logic should still work if you are checking first for the loading
and error
states first, then falling back to the "success" state, but still... it's a good idea to do this
const { status, data } = useQuery(key, fn)
return status === 'loading'
? 'Loading...'
: status === 'error'
? error.message
: data
? 'The Data'
: 'Not Ready'
const { status } = useQuery(key, fn
return status === 'idle' ? 'Not Ready' : status === 'loading'
? 'Loading...'
: status === 'error'
? error.message
: 'The Data'
Do you use queryCache.refetchQueries
?
refetchQueries
has been renamed to invalidateQueries
. You will need make this rename change for your app to continue working propertly. The name change comes due to some differences in what the function does.
queryKey
used in refetchQueries(queryKey)
and were also stale, would be refetched... **even queries that were inactive and not rendered on the screen. This resulted in quite a few queries being refetched regardless of their immediate necessity.invalidateQueries
, only queries that are actively rendered will be refetched, while any other matching queries will forcefully be marked as stale.Did you expect queryCache.refetchQueries
to only refetch stale queries?
invalidateQueries
method will always refetch matching queries that are active. All other matched queries that are not active will be immediately marked as stale.Do you call queryCache.refetchQueries
with the force
option?
force
option was a way to force queries that were not stale to refetch.invalidateQueries
method will always refetch matching queries that are active and all other matched queries that are not active will be immediately marked as stale.Do you use a global configuration object to configure React Query?
const globalConfig = {
suspense,
useErrorBoundary,
throwOnError,
refetchAllOnWindowFocus,
queryKeySerializerFn,
onMutate,
onSuccess,
onError,
onSettled,
retry,
retryDelay,
staleTime,
cacheTime,
refetchInterval,
queryFnParamsFilter,
refetchOnMount,
isDataEqual,
}
shared
section, which is only for the suspense
and queryKeySerializerFn
options (that are inherited into all others) and the queries
and mutations
sections, each corresponding to the functionality they are used for in React Query:
const globalConfig = {
shared: {
suspense,
},
queries: {
suspense, // defaults to `shared.suspense`
queryKeySerializerFn,
enabled,
retry,
retryDelay,
staleTime,
cacheTime,
refetchOnWindowFocus,
refetchInterval,
queryFnParamsFilter,
refetchOnMount,
isDataEqual,
onError,
onSuccess,
onSettled,
throwOnError,
useErrorBoundary,
},
mutations: {
suspense, // defaults to `shared.suspense`
throwOnError,
onMutate,
onError,
onSuccess,
onSettled,
useErrorBoundary,
},
}
Do you use "optional query variables" eg. useQuery(queryKey, optionalVariables, queryFn)
or useQuery({ variables })
?
useQuery('todos', [optional, variables], queryFn)
useQuery('todos', (key) => queryFn(key, optional, variables))
Do you use the globalConfig.refetchAllOnWindowFocus
config option?
refetchAllOnWindowFocus
has been renamed to refetchOnWindowFocus
to match the option in the configuration object for useQuery
and friends.Do you use the refetch
function returned by useQuery
and friends?
refetch
function would not trigger an actual refetch if the query is not stale.refetch
will always trigger a refetch, regardless if the query is stale or not.Do you expect prefetchQuery
to skip the first render of useQuery
instances that render after it?
useQuery
call after a prefetchQuery
would be skipped all the time.staleTime
of a prefetchQuery
instance is honored. So, if you call prefetchQuery(key, fn, { staletime: 5000 })
, and then useQuery(key, fn)
is rendered within those initial 5000 milliseconds, the query will not refetch in the background, since it is not stale yet. Likewise, if the stale time has been reached by the time useQuery(key, fn)
renders, it will refetch in the background, since it is stale when useQuery
mounts/renders.Do you use prefetchQuery
's throwOnError
or force
options?
prefetchQuery
's throwOnError
and force
options are now located in a fourth argument, after the query config.prefetchQuery(key, fn, { ...queryConfig, throwOnError: true, force: true })
prefetchQuery(key, fn, queryConfig, { throwOnError: true, force: true })
Do you call mutate()
with additional side-effect callbacks? eg. mutate(vars, { onError, onSuccess, onSettled })
There are no code changes here, however previously, mutate()
-level side effects would run before side-effects defined in useMutation
. That order has been reversed to make more sense.
Now, the side-effect callbacks in useMutation
will be fired before their mutate
-level counterparts.
Before
const mutate = useMutation(fn, {
onSuccess: () => console.log('I will run second'),
})
mutate(vars, { onSuccess: () => console.log('I will run first') })
After
const mutate = useMutation(fn, {
onSuccess: () => console.log('I will run first'),
})
mutate(vars, { onSuccess: () => console.log('I will run second') })
Do you use setQueryData
to update multiple queries with a single query key? eg. setQueryData('todos', newData)
and expect queryKeys ['todos', 1]
and ['todos', 2]
to both get updated?
setQueryData
no longer allows updating multiple queries at once (via prefix matching). If you need to update multiple queries with the same data, you can use the queryCache.getQueries()
function to match all of the queries you want, then loop over them and use their query.setData
function to set all of them to the same value.The booleans isSuccess
, isError
isLoading
and a new one called isIdle
have been added to the queryInfo object returned by useQuery
(and friends) and useMutation
. These are derived safely from the queryInfo.status
and are guaranteed to not overlap. In most situations, they are easier to use, less typo-prone than status strings and also more terse for determining what to render based on the status of a query.
const queryInfo = useQuery(queryKey, fn)
return queryInfo.isLoading ? (
'Loading...'
) : queryInfo.isError ? (
queryInfo.error.message
) : (
<div>{queryInfo.data}</div>
)
queryCaches
is now exported, which allows you to clean up all query caches that were created. We do this in our own tests when multiple caches are used for testing and to be thorough.
// test.js
import { queryCaches } from 'react-query'
afterEach(() => {
queryCaches.forEach((queryCache) => queryCache.clear())
})
fetchMore
now supports an optional previous
option, which will determine if the data you are fetching is should be prepended instead of appended to your infinite list. eg, fetchMore(nextPageVars, { previous: true })
const { fetchMore } = useInfiniteQuery(queryKey, fn)
return (
<button
onClick={() => fetchMore(previousPageVariables, { previous: true })}
/>
)
refetchInterval
can now be changed on the fly. Check out the auto-refetching example to see it in action!
invalidateQueries
(previously refetchQueries
) now has an option called refetchActive
that when set to false
will not refetch matching queries that are active on the page.
makeQueryCache
now accepts an optional configuration object. The defaultConfig
object is used to override the default query configuration config to use inside of this cache. The frozen
option if set to true
will simulate React Query being run on the server, where no queries are cached for privacy and safety concerns. This is the default when using React Query on the server and is optional. You can also set it to true
on the server and have it work as it would on the client. More information on this coming soon!
Published by tannerlinsley over 4 years ago
Published by tannerlinsley over 4 years ago
Published by tannerlinsley over 4 years ago
Published by tannerlinsley over 4 years ago
Published by tannerlinsley over 4 years ago
Published by tannerlinsley over 4 years ago
Published by tannerlinsley over 4 years ago
Published by tannerlinsley over 4 years ago
isSuccess
, isError
isLoading
and a new one called isIdle
have been added to the queryInfo object returned by useQuery
and friends. These are derived safely from the queryInfo.status
and are guaranteed to not overlap. In most situations, they are easier to use, less typo-prone than status strings and also more terse for determining what to render based on the status of a query.queryCaches
is now exported, which allows you to clean up all query caches that were created. We do this in our own tests when multiple caches are used for testing and to be thorough.fetchMore
now supports an optional previous
option, which will determine if the data you are fetching is should be prepended instead of appended to your infinite list. eg, fetchMore(nextPageVars, { previous: true })
makeQueryCache
now accepts an optional configuration object. The defaultConfig
object is used to override the default query configuration config to use inside of this cache. The frozen
option if set to true
will simulate React Query being run on the server, where no queries are cached for privacy and safety concerns. This is the default when using React Query on the server and is optional. You can also set it to true
on the server and have it work as it would on the client. More information on this coming soon!refetchInterval
can now be changed on the fly. Check out the auto-refetching example to see it in action!enabled
config flag. This flag must be a boolean-esque value, not a function. If you are looking to replace the throwable function option, you should instead use optional chaining, eg. useQuery(user?.id, fn, { enabled: user?.id })
.enabled
option) will now start in a new idle
state if they are initialized with no data and enabled: false
.refetchQueries
has been replace by invalidateQueries
. Previously, refetchQueries
would refetch any query key it matched that was stale, even if it was not currently being used on the screen. This has changed and it will now only refetch active queries (those being subscribed to with useQuery and friends). All other queries that it matches will simply be marked as "stale" and be refetched when they are rendered next, if ever. You can also pass an invalidateQueries(queryKey, { refetchActive: false })
option if you do not want active queries to refetch either. This should save some bandwidth for queries that were cached, but not in use that will no longer be fetched again until they are needed.shared
, queries
and mutations
const globalConfig = {
shared: {
suspense,
queryKeySerializerFn,
},
queries: {
...shared,
enabled,
retry,
retryDelay,
staleTime,
cacheTime,
refetchOnWindowFocus,
refetchInterval,
queryFnParamsFilter,
refetchOnMount,
isDataEqual,
onError,
onSuccess,
onSettled,
throwOnError,
useErrorBoundary,
},
mutations: {
...shared,
throwOnError,
onMutate,
onError,
onSuccess,
onSettled,
useErrorBoundary,
},
}
force
options have been removed. Functions that are meant to update the query always will. If you need to check that a query is stale before calling one of these functions, you can use queryCache.get(queryKey).state.isStale
to do so.queryVariables
have been removed. These didn't make much sense to begin with, and if you still need them, you can just inline them in your query function anyway, eg. useQuery(['hello', 'world'], (a, b) => queryFn(a, b, customVariable1, customVariable2))
enabled
config optionglobalConfig.refetchAllOnWindowFocus
, which previous overlapped in fuctionality with the query-level refetchOnWindowFocus
has been consolidated to a single refetchOnWindowFocus
that can set in the the global config.queries.refetchOnWindowFocus
and also on a per query basis.refetch
function returned by useQuery and friends will now always trigger a refetch for the query, regardless if the query is stale or not. This is way more clear and reliable to deal with.prefetchQuery
will no longer disable the next render of that query using useQuery (and friends). Instead, the staleTime
will be respected for the prefetchQuery call, so if prefetchQuery(key, fn, { staletime: 5000 })
is called, and then useQuery(key, fn, { staleTime: 1000 })
is rendered within those initial 5000 milliseconds, the query will not refetch in the background. But if the stale time has been reached by the time useQuery renders, it will refetch in the background.prefetchQuery
's force
option has been removed. When you call prefetchQuery
, the queryFn will always be called, regardless if the query is stale or not.prefetchQuery
's throwOnError
option is now located in a fourth argument, after the query config, eg. prefetchQuery(key, fn, config, { throwOnError: true })