When the component is mounted, it automatically triggers data fetching and returns data, loading status, and error information, supported by useAsyncFn.
// fetchData is independent of the request library, it can be any async function that returns a Promise, which can be implemented by fetch, axios, graphql, etc.const { loading, data, error } =useQuery(fetchData)// Loading and error UI handlingif (loading) return <Loading />if (error) return <Error />// Rendering datareturn <div>{data}</div>
When manual is set to true, all built-in automatic behaviors (none of which are enabled by default, including polling loading, focus reloading, network reconnect reloading) are disabled. Also, the default value of immediate is set to false.
const { run, loading, data, error, params } =useQuery(fetchData, {manual: true,initialParams: ['params'],initialData: 'initialData',})// Manually triggered, which will trigger the update of the paramsrun('newParams')
Using refreshDependencies, you can set the dependencies for the refresh operation. When any of these dependencies change, a refresh (refresh()) operation will be triggered, supported by useUpdateEffect.
Using cancel can cancel the current request and reset all states. Note that cancelcannot prevent the Promise from executing, it just terminates the subsequent status update logic, supported by useAsyncFn.
Using loadingSlow can determine whether the current operation is in a slow loading state, that is, the operation time exceeds the expected threshold. By using this state to render different UIs, user experience can be improved, supported by useLoadingSlowFn.
const { loading, loadingSlow, data, error } =useQuery(fetchData, {loadingTimeout: 3_000, // Default is 0, set to 3 seconds hereonLoadingSlow: () =>console.log('loading slow'), // Callback for slow loading})// Display slow loading UI during slow loadingif (loading) return <Loadingslow={loadingSlow} />
The params can be used to retrieve the parameters of the last request, and refresh can be used to re-request with the parameters of the last request, supported by useAsyncFn.
const { run, params, refresh } =useQuery(fetchData)// Retrieve the parameters of the last request, which will be `initialParams` on the first call if it exists, otherwise it will be [] on the first callconsole.log(params)// Re-request with the last parameters, i.e., 'refresh', equivalent to `run(params)`refresh()
The clearBeforeRun can be used to clear the data before each request, and cancelOnUnmount can be used to automatically cancel the request logic when the component is unmounted (but cannot prevent the Promise from executing), supported by useAsyncFn.
const { loading, data, error } =useQuery(fetchData, {clearBeforeRun: true, // Clear data before each request, default is falsecancelOnUnmount: false, // Do not cancel the request when the component is unmounted, default is true})
Using throttle and debounce options can control the frequency of manual triggering, supported by useThrottledFn and useDebouncedFn.
const { run, loading, data, error } =useQuery(fetchData, {throttle: 1_000, // In cases of frequent triggering, limit triggering to once per second// throttle: { wait: 1_000 }, // Or specify the entire UseThrottledFnOptions objectdebounce: 1_000, // In cases of frequent triggering, trigger 1 second after the operation stops// debounce: { wait: 1_000 }, // Or specify the entire UseDebouncedFnOptions object})
Setting refreshInterval to a number greater than 0 will enable the automatic refresh function, fetching data again at specified intervals, supported by useIntervalFn.
const { loading, data, error } =useQuery(fetchData, {refreshInterval: 5_000, // Polling interval, default 0, offrefreshWhenHidden: true, // Whether to poll when the page is not visible, default falserefreshWhenOffline: true, // Whether to poll when offline, default false})
Setting refreshOnFocus and refreshOnReconnect to true will fetch data again when the page is focused or the network is reconnected, supported by useReFocusFn and useReConnectFn.
const { loading, data, error } =useQuery(fetchData, {refreshOnFocus: true,refreshOnReconnect: true,refreshOnFocusThrottleWait: 3_000, // Throttle time for refresh on focus, default 5_000, only effective when refreshOnFocus is true})
For usage in non-Web environments like React Native, Ink, you can manually specify the logic for visibility and network status.
If manual is not specifically set to false, but you still want to control internal automatic behaviors, you can use the Pausable instance attribute exposed by the Hooks, supported by usePausable.
const { pause, resume, isActive } =useQuery(fetchData, {refreshInterval: 5_000, // Specify to refresh every 5 seconds})// Pause automatic behaviorspause()// Resume automatic behaviorsresume()// Check if it is in an active stateconsole.log(isActive())
Setting a cacheKey enables caching functionality. The cached content includes data and param. If cached data exists and has not expired (expired data will be cleared), it will return the cached data first, while still triggering a request to update the cached data, thus ensuring the freshness of the data. This is the SWR (Stale-While-Revalidate) strategy.
const { loading, data, error } =useQuery(fetchData, {cacheKey: 'cacheKey', // Cache key, can be a string or a function returning a stringcacheExpirationTime: 5*60*1000, // Maximum cache time, default 5 minutes, set `false` to disable})
You can specify provider as an external storage (such as Reactive), localStorage, etc., to achieve multi-location shared caching or more detailed local caching. A Provider needs to meet the following interface definition (basically the Map type interface):
For instance, some parts can use an independent Map cache for data sharing:
constcache=newMap<string, any>()// Component Aconst { loading, data, error } =useQuery(fetchData, {cacheKey: 'cacheKeyA', provider: cache, // Using an independent Map as the cache provider})// Component Bconst { loading, data, error } =useQuery(fetchData, {cacheKey: 'cacheKeyB', provider: cache, // Using an independent Map as the cache provider})// Component C, although using the same cacheKey as A, doesn't share the cache because of a different providerconst { loading, data, error } =useQuery(fetchData, {cacheKey: 'cacheKeyA', // Not specifying a provider, using the default global shared Map})
Or using localStorage as the cache provider to achieve data persistence after page refreshes.
If both cacheKey and provider are the same, they will be considered as the same cache. Any state, data, or request change in one part of the cache will be synchronized to other parts.
This situation is common when multiple components use the same data set, such as user information, which may be used in nav components, header components, sidebar components, etc. In this case, cacheKey and provider can be used to share data.
// Component Aconst { loading, data, mutate, refresh } =useQuery(fetchData, {cacheKey: 'cacheKey',})// Component Bconst { data, params } =useQuery(fetchData, {cacheKey: 'cacheKey',})// Execute refresh or mutate operation in Component Arefresh()mutate('newData', ['newParams'])// In Component B, data and params will be updated synchronouslyconsole.log(data, params) // 'newData', ['newParams']
By using compare, you can customize the logic for data updates to prevent frequent refreshes. This is particularly useful in dealing with some pseudo-differences in data, such as timestamps, and it can reduce unnecessary rendering, shallowEqual is used by default, supported by useAsyncFn.
const { loading, data, error } =useQuery(fetchData, {compare: (preData, nextData) => {// Compare whether the data is the same, return true to not update, return false to updatereturnpreData===nextData// Or compare a certain field of data, for example, the timestamp might be different, but the actual effective data is the samereturndeepCompare(preData?.data, nextData?.data)// But please note, when the data size is too large, deep comparison will affect performance, so use it judiciously },})
useQuery implements a dependency collection strategy, achieving on-demand rendering and maximizing performance optimization, supported internally by useTrackedRefState.
// All state changes will trigger re-rendering, not recommended!!!constfn=useQuery(fetchData)// Changes in loading, data, or error states will trigger re-renderingconst { loading, data, error } =useQuery(fetchData)// Only changes in the loading state will trigger re-rendering; changes in data and error states will not.const { loading } =useQuery(fetchData)// All supported state attributes for dependency collectionconst { loading, data, error, params, loadingSlow, initializing, refreshing } =useQuery(fetchData)
exportinterfaceUseQueryOptions<TextendsAnyFunc, D=Awaited<ReturnType<T>>, E=any>extendsOmit<UseLoadingSlowFnOptions<T, D, E>, 'initialValue'>,Pick<UseReConnectOptions, 'registerReConnect'>,Pick<UseReFocusOptions, 'registerReFocus'> {/** * Disable all automatic refresh behaviors, default is off * * @defaultValue false */manual?: boolean/** * Initial data passed to fetcher when first mount * * @defaultValue undefined */initialData?: D | undefined/** * Cache key, can be a string or a function that returns a string * * @defaultValue undefined */cacheKey?: string | ((...args: Parameters<T> | []) =>string)/** * Max cache time, will clear the cache after the specified time * * default is 5 minutes, set `false` to disable */cacheExpirationTime?: number | false/** * Cache provider, it can be set to an external store (reactive), localStorage, etc. * * Needs to comply with the CacheLike interface definition, defaults to a globally shared `new Map()` * * @defaultValue global shared `new Map()` */provider?: Gettable<CacheLike<D>>/** * ThrottleOptions => only affects the frequency of manually executing the run method * * @defaultValue undefined */throttle?: UseThrottledFnOptions['wait'] | UseThrottledFnOptions/** * DebounceOptions => only affects the frequency of manually executing the run method * * @defaultValue undefined */debounce?: UseDebouncedFnOptions['wait'] | UseDebouncedFnOptions/** * Whether to reload when focus is obtained, default is off * * @defaultValue false */refreshOnFocus?: boolean/** * Throttle time when obtaining focus, default 5_000 (ms), only valid when `refreshOnFocus` is true * * @defaultValue 5_000 */refreshOnFocusThrottleWait?: number/** * Custom visibility judgment function * * @defaultValue defaultIsVisible */isVisible?: () =>Promisable<boolean>/** * Whether to reload when network reconnects, default is off * * @defaultValue false */refreshOnReconnect?: boolean/** * Custom online judgment function * * @defaultValue defaultIsOnline */isOnline?: () =>Promisable<boolean>/** * Interval time for automatic refresh, default is 0, off * * @defaultValue 0 */refreshInterval?: Exclude<UseIntervalFnInterval, 'requestAnimationFrame'>/** * Whether to reload when hidden, default is off * * @defaultValue false */refreshWhenHidden?: boolean/** * Whether to reload when offline, default is off * * @defaultValue false */refreshWhenOffline?: boolean/** * The dependencies of the refresh operation, when the dependencies change, the refresh operation will be triggered * * @defaultValue [] */refreshDependencies?: DependencyList/** * Error retry count * * @defaultValue 0 */errorRetryCount?: UseRetryFnOptions<E>['count']/** * Error retry interval * * @defaultValue 0 */errorRetryInterval?: UseRetryFnOptions<E>['interval']/** * Whether to clear the cache before each request * * @defaultValue false */onErrorRetry?: UseRetryFnOptions<E>['onErrorRetry']}
exportinterfaceUseQueryReturns<TextendsAnyFunc, D=Awaited<ReturnType<T>>, E=any>extendsPausable,Omit<UseLoadingSlowFnReturns<T, D, E>, 'value'> {/** * The data returned by the request */data: D | undefined/** * Whether the request is in the initialization state (no data + loading, initializing => !data && loading) */initializing: boolean/** * Whether the request is refreshing data (has data + loading, refreshing => data && loading) */refreshing: boolean}