UNPKG

113 kBMarkdownView Raw
1![React Query Header](https://github.com/tannerlinsley/react-query/raw/master/media/header.png)
2
3<img src='https://github.com/tannerlinsley/react-query/raw/master/media/logo.png' width='300'/>
4
5Hooks for fetching, caching and updating asynchronous data in React
6
7<a href="https://twitter.com/intent/tweet?button_hashtag=TanStack" target="\_parent">
8 <img alt="#TanStack" src="https://img.shields.io/twitter/url?color=%2308a0e9&label=%23TanStack&style=social&url=https%3A%2F%2Ftwitter.com%2Fintent%2Ftweet%3Fbutton_hashtag%3DTanStack">
9</a><a href="https://github.com/tannerlinsley/react-query/actions?query=workflow%3A%22react-query+tests%22">
10<img src="https://github.com/tannerlinsley/react-query/workflows/react-query%20tests/badge.svg" />
11</a><a href="https://npmjs.com/package/react-query" target="\_parent">
12 <img alt="" src="https://img.shields.io/npm/dm/react-query.svg" />
13</a><a href="https://bundlephobia.com/result?p=react-query@latest" target="\_parent">
14 <img alt="" src="https://badgen.net/bundlephobia/minzip/react-query@latest" />
15</a><a href="#badge">
16 <img alt="semantic-release" src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg">
17 </a><a href="https://github.com/tannerlinsley/react-query/discussions">
18 <img alt="Join the discussion on Github" src="https://img.shields.io/badge/Github%20Discussions%20%26%20Support-Chat%20now!-blue" />
19</a><a href="https://github.com/tannerlinsley/react-query" target="\_parent">
20 <img alt="" src="https://img.shields.io/github/stars/tannerlinsley/react-query.svg?style=social&label=Star" />
21</a><a href="https://twitter.com/tannerlinsley" target="\_parent">
22 <img alt="" src="https://img.shields.io/twitter/follow/tannerlinsley.svg?style=social&label=Follow" />
23</a>
24
25Enjoy this library? Try them all! [React Table](https://github.com/tannerlinsley/react-table), [React Form](https://github.com/tannerlinsley/react-form), [React Charts](https://github.com/tannerlinsley/react-charts)
26
27## Quick Features
28
29- Transport/protocol/backend agnostic data fetching (REST, GraphQL, promises, whatever!)
30- Auto Caching + Refetching (stale-while-revalidate, Window Refocus, Polling/Realtime)
31- Parallel + Dependent Queries
32- Mutations + Reactive Query Refetching
33- Multi-layer Cache + Automatic Garbage Collection
34- Paginated + Cursor-based Queries
35- Load-More + Infinite Scroll Queries w/ Scroll Recovery
36- Request Cancellation
37- [React Suspense](https://reactjs.org/docs/concurrent-mode-suspense.html) + Fetch-As-You-Render Query Prefetching
38- [Dedicated Devtools (React Query Devtools)](https://github.com/tannerlinsley/react-query-devtools)
39- 4kb - 6kb (depending on features imported) <a href="https://bundlephobia.com/result?p=react-query@latest" target="\_parent">
40 <img alt="" src="https://badgen.net/bundlephobia/minzip/react-query@latest" />
41 </a>
42
43<details>
44<summary>Core Issues and Solution</summary>
45
46## The Challenge
47
48Tools for managing "global state" are plentiful these days, but most of these tools:
49
50- Mistake **server cache state** for **global state**
51- Force you to manage async data in a synchronous way
52- Duplicate unnecessary network operations
53- Use naive or over-engineered caching strategies
54- Are too basic to handle large-scale apps or
55- Are too complex or built for highly-opinionated systems like Redux, GraphQL, [insert proprietary tools], etc.
56- Do not provide tools for server mutations
57- Either do not provide easy access to the cache or do, but expose overpowered foot-gun APIs to the developer
58
59## The Solution
60
61React Query exports a set of hooks that address these issues. Out of the box, React Query:
62
63- Separates your **server cache state** from your **global state**
64- Provides async aware APIs for reading and updating server state/cache
65- Dedupes both async and sync requests to async resources
66- Automatically caches data, invalidates and refetches stale data, and manages garbage collection of unused data
67- Scales easily as your application grows
68- Is based solely on Promises, making it highly unopinionated and interoperable with any data fetching strategy including REST, GraphQL and other transactional APIs
69- Provides an integrated promise-based mutation API
70- Opt-in Manual or Advance cache management
71
72</details>
73
74<details>
75<summary>Inspiration & Hat-Tipping</summary>
76<br />
77A big thanks to both [Draqula](https://github.com/vadimdemedes/draqula) for inspiring a lot of React Query's original API and documentation and also [Zeit's SWR](https://github.com/zeit/swr) and its creators for inspiring even further customizations and examples. You all rock!
78
79</details>
80
81<details>
82<summary>How is this different from Zeit's SWR?</summary>
83<br />
84
85[Zeit's SWR](https://github.com/zeit/swr) is a great library, and is very similar in spirit and implementation to React Query with a few notable differences:
86
87- Automatic Cache Garbage Collection - React Query handles automatic cache purging for inactive queries and garbage collection. This can mean a much smaller memory footprint for apps that consume a lot of data or data that is changing often in a single session
88- No Default Data Fetcher Function - React Query does not ship with a default fetcher (but can easily be wrapped inside of a custom hook to achieve the same functionality)
89- `useMutation` - A dedicated hook for handling generic lifecycles around triggering mutations and handling their side-effects in applications. SWR does not ship with anything similar, and you may find yourself reimplementing most if not all of `useMutation`'s functionality in user-land. With this hook, you can extend the lifecycle of your mutations to reliably handle successful refetching strategies, failure rollbacks and error handling.
90- Prefetching - React Query ships with 1st class prefetching utilities which not only come in handy with non-suspenseful apps but also make fetch-as-you-render patterns possible with React Query. SWR does not come with similar utilities and relies on `<link rel='preload'>` and/or manually fetching and updating the query cache
91- Query cancellation integration is baked into React Query. You can easily use this to wire up request cancellation in most popular fetching libraries, including but not limited to fetch and axios.
92- Query Key Generation - React Query uses query key generation, query variables, and implicit query grouping. The query key and variables that are passed to a query are less URL/Query-based by nature and much more flexible. All items supplied to the query key array are used to compute the unique key for a query (using a stable and deterministic sorting/hashing implementation). This means you can spend less time thinking about precise key matching, but more importantly, allows you to use partial query-key matching when refetching, updating, or removing queries in mass eg. you can refetch every query that starts with a `todos` in its key, regardless of variables, or you can target specific queries with (or without) variables, and even use functional filtering to select queries in most places. This architecture is much more robust and forgiving especially for larger apps.
93
94</details>
95
96## Used By
97
98- [Google](https://google.com)
99- [PayPal](https://paypal.com)
100- [Amazon](https://amazon.com)
101- [Walmart](https://walmart.com)
102- [Microsoft](https://microsoft.com)
103- [Target](https://target.com)
104- [HP](https://hp.com)
105- [Major League Baseball Association](https://www.mlb.com)
106- [Volvo](https://www.volvocars.com)
107- [Ocado](https://ocado.com)
108- [UPC.ch](https://upc.ch)
109- [EFI.com](https://efi.com)
110- [ReactBricks](https://www.reactbricks.com/)
111- [Nozzle.io](https://nozzle.io)
112
113> _These analytics are made available via the awesome [Scarf](https://www.npmjs.com/package/@scarf/scarf) package analytics library_
114
115## Examples
116
117- Basic - [CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-query/tree/master/examples/basic) - [Source](./examples/basic)
118- Custom Hooks - [CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-query/tree/master/examples/custom-hooks) - [Source](./examples/custom-hooks)
119- Auto Refetching / Polling / Realtime - [CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-query/tree/master/examples/auto-refetching) - [Source](./examples/auto-refetching)
120- Window Refocus Refetching - [CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-query/tree/master/examples/focus-refetching) - [Source](./examples/focus-refetching)
121- Optimistic Updates - [CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-query/tree/master/examples/optimistic-updates) - [Source](./examples/optimistic-updates)
122- Pagination - [CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-query/tree/master/examples/pagination) - [Source](./examples/pagination)
123- Load-More & Infinite Scroll - [CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-query/tree/master/examples/load-more-infinite-scroll) - [Source](./examples/load-more-infinite-scroll)
124- Suspense - [CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-query/tree/master/examples/suspense) - [Source](./examples/suspense)
125- Playground (with devtools) - [CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-query/tree/master/examples/playground) - [Source](./examples/playground)
126- Star Wars (with devtools) - [CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-query/tree/master/examples/star-wars) - [Source](./examples/star-wars)
127- Rick And Morty (with devtools) - [CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-query/tree/master/examples/rick-morty) - [Source](./examples/rick-morty)
128
129## Sponsors
130
131This library is being built and maintained by me, @tannerlinsley and I am always in need of more support to keep projects like this afloat. If you would like to get premium support, add your logo or name on this README, or simply just contribute to my open source Sponsorship goal, [visit my Github Sponsors page!](https://github.com/sponsors/tannerlinsley/)
132
133<table>
134 <tbody>
135 <tr>
136 <td align="center" valign="middle">
137 <a href="https://github.com/sponsors/tannerlinsley" target="_blank">
138 <img width='150' src="https://raw.githubusercontent.com/tannerlinsley/files/master/images/patreon/diamond.png">
139 </a>
140 </td>
141 <td align="center" valign="middle">
142 <a href="https://github.com/sponsors/tannerlinsley" target="_blank">
143 Become a Sponsor!
144 </a>
145 </td>
146 </tr>
147 </tbody>
148</table>
149
150<table>
151 <tbody>
152 <tr>
153 <td align="center" valign="middle">
154 <a href="https://github.com/sponsors/tannerlinsley/" target="_blank">
155 <img width='150' src="https://raw.githubusercontent.com/tannerlinsley/files/master/images/patreon/platinum.png">
156 </a>
157 </td>
158 <td align="center" valign="middle">
159 <a href="https://github.com/sponsors/tannerlinsley" target="_blank">
160 Become a Sponsor!
161 </a>
162 </td>
163 </tr>
164 </tbody>
165</table>
166
167<table>
168 <tbody>
169 <tr>
170 <td align="center" valign="middle">
171 <a href="https://github.com/sponsors/tannerlinsley/" target="_blank">
172 <img width='150' src="https://raw.githubusercontent.com/tannerlinsley/files/master/images/patreon/gold.png">
173 </a>
174 </td>
175 <td align="center" valign="middle">
176 <a href="https://nozzle.io" target="_blank">
177 <img width='225' src="https://nozzle.io/img/logo-blue.png">
178 </a>
179 </td>
180 <td align="center" valign="middle">
181 <a href="https://github.com/sponsors/tannerlinsley" target="_blank">
182 Become a Sponsor!
183 </a>
184 </td>
185 </tr>
186 </tbody>
187</table>
188
189<table>
190 <tbody>
191 <tr>
192 <td align="center" valign="middle">
193 <a href="https://github.com/sponsors/tannerlinsley/" target="_blank">
194 <img width='150' src="https://raw.githubusercontent.com/tannerlinsley/files/master/images/patreon/silver.png">
195 </a>
196 </td>
197 <td align="center" valign="middle">
198 <a href="https://www.reactbricks.com/" target="_blank">
199 <img width='170' src="https://www.reactbricks.com/reactbricks_vertical.svg">
200 </a>
201 </td>
202 <td align="center" valign="middle">
203 <a href="https://github.com/sponsors/tannerlinsley" target="_blank">
204 Become a Sponsor!
205 </a>
206 </td>
207 </tr>
208 </tbody>
209</table>
210
211<table>
212 <tbody>
213 <tr>
214 <td valign="top">
215 <a href="https://github.com/sponsors/tannerlinsley/">
216 <img width='150' src="https://raw.githubusercontent.com/tannerlinsley/files/master/images/patreon/supporters.png" />
217 </a>
218 </td>
219 <td>
220 <ul>
221 <li><a href="https://github.com/bgazzera">@bgazzera<a></li>
222 <li><a href="https://kentcdodds.com/"> Kent C. Dodds (kentcdodds.com)</a></li>
223 </ul>
224 </td>
225 <td>
226 <a href="https://github.com/sponsors/tannerlinsley" target="_blank">
227 Become a Supporter!
228 </a>
229 </td>
230 </tr>
231 </tbody>
232</table>
233
234<table>
235 <tbody>
236 <tr>
237 <td valign="top">
238 <a href="https://github.com/sponsors/tannerlinsley/">
239 <img width='150' src="https://raw.githubusercontent.com/tannerlinsley/files/master/images/patreon/fans.png" />
240 </a>
241 </td>
242 <!-- <td>
243 <ul>
244 <li></li>
245 </ul>
246 </td> -->
247 <td>
248 <a href="https://github.com/sponsors/tannerlinsley" target="_blank">
249 Become a Fan!
250 </a>
251 </td>
252 </tr>
253 </tbody>
254</table>
255
256# Documentation
257
258<!-- START doctoc generated TOC please keep comment here to allow auto update -->
259<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
260
261
262- [Installation](#installation)
263- [Defaults to keep in mind](#defaults-to-keep-in-mind)
264- [Queries](#queries)
265 - [Query Keys](#query-keys)
266 - [Query Key Variables](#query-key-variables)
267 - [Optional Variables](#optional-variables)
268 - [Using a Query Object instead of parameters](#using-a-query-object-instead-of-parameters)
269 - [Dependent Queries](#dependent-queries)
270 - [Caching & Invalidation](#caching--invalidation)
271 - [Paginated Queries with `usePaginatedQuery`](#paginated-queries-with-usepaginatedquery)
272 - [Load-More & Infinite-Scroll with `useInfiniteQuery`](#load-more--infinite-scroll-with-useinfinitequery)
273 - [Scroll Restoration](#scroll-restoration)
274 - [Manual Querying](#manual-querying)
275 - [Retries](#retries)
276 - [Retry Delay](#retry-delay)
277 - [Prefetching](#prefetching)
278 - [Initial Data](#initial-data)
279 - [Initial Data Function](#initial-data-function)
280 - [Initial Data from Cache](#initial-data-from-cache)
281 - [SSR & Initial Data](#ssr--initial-data)
282 - [Suspense Mode](#suspense-mode)
283 - [Fetch-on-render vs Fetch-as-you-render](#fetch-on-render-vs-fetch-as-you-render)
284 - [Canceling Query Requests](#canceling-query-requests)
285- [Mutations](#mutations)
286 - [Basic Mutations](#basic-mutations)
287 - [Mutation Variables](#mutation-variables)
288 - [Invalidate and Refetch Queries from Mutations](#invalidate-and-refetch-queries-from-mutations)
289 - [Query Updates from Mutations](#query-updates-from-mutations)
290 - [Resetting Mutation State](#resetting-mutation-state)
291 - [Manually or Optimistically Setting Query Data](#manually-or-optimistically-setting-query-data)
292 - [Optimistic Updates with Automatic Rollback for Failed Mutations](#optimistic-updates-with-automatic-rollback-for-failed-mutations)
293- [Displaying Background Fetching Loading States](#displaying-background-fetching-loading-states)
294- [Displaying Global Background Fetching Loading State](#displaying-global-background-fetching-loading-state)
295- [Window-Focus Refetching](#window-focus-refetching)
296 - [Custom Window Focus Event](#custom-window-focus-event)
297 - [Ignoring Iframe Focus Events](#ignoring-iframe-focus-events)
298- [Custom Query Key Serializers (Experimental)](#custom-query-key-serializers-experimental)
299- [React Query Devtools](#react-query-devtools)
300- [API](#api)
301 - [`useQuery`](#usequery)
302 - [`usePaginatedQuery`](#usepaginatedquery)
303 - [`useInfiniteQuery`](#useinfinitequery)
304 - [`useMutation`](#usemutation)
305 - [`queryCache`](#querycache)
306 - [`queryCache.prefetchQuery`](#querycacheprefetchquery)
307 - [`queryCache.getQueryData`](#querycachegetquerydata)
308 - [`queryCache.setQueryData`](#querycachesetquerydata)
309 - [`queryCache.refetchQueries`](#querycacherefetchqueries)
310 - [`queryCache.removeQueries`](#querycacheremovequeries)
311 - [`queryCache.getQuery`](#querycachegetquery)
312 - [`queryCache.getQueries`](#querycachegetqueries)
313 - [`queryCache.isFetching`](#querycacheisfetching)
314 - [`queryCache.subscribe`](#querycachesubscribe)
315 - [`queryCache.clear`](#querycacheclear)
316 - [`useIsFetching`](#useisfetching)
317 - [`ReactQueryConfigProvider`](#reactqueryconfigprovider)
318 - [`setConsole`](#setconsole)
319- [Contributors ✨](#contributors-)
320
321<!-- END doctoc generated TOC please keep comment here to allow auto update -->
322
323# Installation
324
325```bash
326$ npm i --save react-query
327# or
328$ yarn add react-query
329```
330
331React Query uses [Scarf](https://www.npmjs.com/package/@scarf/scarf) to collect anonymized installation analytics. These analytics help support the maintainers of this library. However, if you'd like to opt out, you can do so by setting `scarfSettings.enabled = false` in your project's `package.json`. Alternatively, you can set the environment variable `SCARF_ANALYTICS=false` before you install.
332
333# Defaults to keep in mind
334
335Out of the box, React Query is configured with **aggressive but sane** defaults. **Sometimes these defaults can catch new users off guard or make learning/debugging difficult if they are unknown by the user.** Keep them in mind as you continue to learn and use React Query:
336
337- Query results that are _currently rendered on the screen_ will become "stale" immediately after they are resolved and will be refetched automatically in the background when they are rendered or used again. To change this, you can alter the default `staleTime` for queries to something other than `0` milliseconds.
338- Query results that become unused (all instances of the query are unmounted) will still be cached in case they are used again for a default of 5 minutes before they are garbage collected. To change this, you can alter the default `cacheTime` for queries to something other than `1000 * 60 * 5` milliseconds.
339- Stale queries will automatically be refetched in the background **when the browser window is refocused by the user**. You can disable this using the `refetchOnWindowFocus` option in queries or the global config.
340- Queries that fail will silently and automatically be retried **3 times, with exponential backoff delay** before capturing and displaying an error to the UI. To change this, you can alter the default `retry` and `retryDelay` options for queries to something other than `3` and the default exponential backoff function.
341- Query results by default are deep compared to detect if data has actually changed and if not, the data reference remains unchanged to better help with value stabilization with regards to useMemo and useCallback. The default deep compare function use here (`config.isDataEqual`) only supports comparing JSON-compatible primitives. If you are dealing with any non-json compatible values in your query responses OR are seeing performance issues with the deep compare function, you should probably disable it (`config.isDataEqual = () => false`) or customize it to better fit your needs.
342
343# Queries
344
345To make a new query, call the `useQuery` hook with at least:
346
347- A **unique key for the query**
348- An **asynchronous function (or similar then-able)** to resolve the data
349
350```js
351import { useQuery } from 'react-query'
352
353function App() {
354 const info = useQuery('todos', fetchTodoList)
355}
356```
357
358The **unique key** you provide is used internally for refetching, caching, deduping related queries.
359
360The query `info` returned contains all information about the query and can be easily destructured and used in your component:
361
362```js
363function Todos() {
364 const { status, data, error } = useQuery('todos', fetchTodoList)
365
366 if (status === 'loading') {
367 return <span>Loading...</span>
368 }
369
370 if (status === 'error') {
371 return <span>Error: {error.message}</span>
372 }
373
374 // also status === 'success', but "else" logic works, too
375 return (
376 <ul>
377 {data.map(todo => (
378 <li key={todo.id}>{todo.title}</li>
379 ))}
380 </ul>
381 )
382}
383```
384
385## Query Keys
386
387At its core, React Query manages query caching for you and uses a serializable array or "query key" to do this. Using a query key that is **simple** and **unique to the query's data** is very important. In other similar libraries, you'll see the use of URLs and/or GraphQL query template strings to achieve this, but we believe at scale, this becomes prone to typos and errors. To relieve this issue, React Query Keys can be **strings** or **an array with a string and then any number of serializable primitives and/or objects**.
388
389### String-Only Query Keys
390
391The simplest form of a key is actually not an array, but an individual string. When a string query key is passed, it is converted to an array internally with the string as the only item in the query key. This format is useful for:
392
393- Generic List/Index resources
394- Non-hierarchical resources
395
396```js
397// A list of todos
398useQuery('todos', ...) // queryKey === ['todos']
399
400// Something else, whatever!
401useQuery('somethingSpecial', ...) // queryKey === ['somethingSpecial']
402```
403
404### Array Keys
405
406When a query needs more information to uniquely describe its data, you can use an array with a string and any number of serializable objects to describe it. This is useful for:
407
408- Specific resources
409 - It's common to pass an ID, index, or other primitive
410- Queries with additional parameters
411 - It's common to pass an object of additional options
412
413```js
414// An individual todo
415useQuery(['todo', 5], ...)
416// queryKey === ['todo', 5]
417
418// And individual todo in a "preview" format
419useQuery(['todo', 5, { preview: true }], ...)
420// queryKey === ['todo', 5, { preview: 'true' } }]
421
422// A list of todos that are "done"
423useQuery(['todos', { type: 'done' }], ...)
424// queryKey === ['todos', { type: 'done' }]
425```
426
427### Query Keys are serialized deterministically!
428
429This means that no matter the order of keys in objects, all of the following queries would result in the same final query key of `['todos', { page, status }]`:
430
431```js
432useQuery(['todos', { status, page }], ...)
433useQuery(['todos', { page, status }], ...)
434useQuery(['todos', { page, status, other: undefined }], ...)
435```
436
437The following query keys, however, are not equal. Array item order matters!
438
439```js
440useQuery(['todos', status, page], ...)
441useQuery(['todos', page, status], ...)
442useQuery(['todos', undefined, page, status], ...)
443```
444
445## Query Key Variables
446
447To use external props, state, or variables in a query function, it's easiest to pass them as items in your array query keys! All query keys get passed through to your query function as parameters in the order they appear in the array key:
448
449```js
450function Todos({ completed }) {
451 const { status, data, error } = useQuery(
452 ['todos', { status, page }],
453 fetchTodoList
454 )
455}
456
457// Access the key, status and page variables in your query function!
458function fetchTodoList(key, { status, page }) {
459 return new Promise()
460 // ...
461}
462```
463
464If you send through more items in your query key, they will also be available in your query function:
465
466```js
467function Todo({ todoId, preview }) {
468 const { status, data, error } = useQuery(
469 ['todo', todoId, { preview }],
470 fetchTodoById
471 )
472}
473
474// Access status and page in your query function!
475function fetchTodoById(key, todoId, { preview }) {
476 return new Promise()
477 // ...
478}
479```
480
481Whenever a query's key changes, the query will automatically update. In the following example, a new query is created whenever `todoId` changes:
482
483```js
484function Todo({ todoId }) {
485 const { status, data, error } = useQuery(['todo', todoId], fetchTodo)
486}
487```
488
489## Optional Variables
490
491In some scenarios, you may find yourself needing to pass extra information to your query that shouldn't (or doesn't need to be) a part of the query key. `useQuery`, `usePaginatedQuery` and `useInfiniteQuery` all support passing an optional array of additional parameters to be passed to your query function:
492
493```js
494function Todo({ todoId, preview }) {
495 const { status, data, error } = useQuery(
496 // These will be used as the query key
497 ['todo', todoId],
498 // These will get passed directly to our query function
499 [
500 debug,
501 {
502 foo: true,
503 bar: false,
504 },
505 ],
506 fetchTodoById
507 )
508}
509
510function fetchTodoById(key, todoId, debug, { foo, bar }) {
511 return new Promise()
512 // ...
513}
514```
515
516## Using a Query Object instead of parameters
517
518Anywhere the `[queryKey, variables, queryFn, config]` options are supported throughout React Query's API, you can also use an object to express the same configuration:
519
520```js
521import { useQuery } from 'react-query'
522
523useQuery({
524 queryKey: ['todo', 7],
525 queryFn: fetchTodos,
526 variables: [],
527 config: {},
528})
529```
530
531## Dependent Queries
532
533React Query makes it easy to make queries that depend on other queries for both:
534
535- Parallel Queries (avoiding waterfalls) and
536- Serial Queries (when a piece of data is required for the next query to happen).
537
538To do this, you can use the following 2 approaches:
539
540### Pass a falsy query key
541
542If a query isn't ready to be requested yet, just pass a falsy value as the query key or as an item in the query key:
543
544```js
545// Get the user
546const { data: user } = useQuery(['user', email], getUserByEmail)
547
548// Then get the user's projects
549const { data: projects } = useQuery(
550 // `user` would be `null` at first (falsy),
551 // so the query will not execute while the query key is falsy
552 user && ['projects', user.id],
553 getProjectsByUser
554)
555```
556
557### Use a query key function that throws an exception
558
559If a function is passed, the query will not execute until the function can be called without throwing:
560
561```js
562// Get the user
563const { data: user } = useQuery(['user', email])
564
565// Then get the user's projects
566const { data: projects } = useQuery(
567 // This will throw trying to access property `id` of `undefined` until the `user` is available
568 () => ['projects', user.id]
569)
570```
571
572## Caching & Invalidation
573
574React Query caching is automatic out of the box. It uses a `stale-while-revalidate` in-memory caching strategy together with robust query deduping to always ensure a query's data is only cached when it's needed and only cached once even if that query is used multiple times across your application.
575
576At a glance:
577
578- The cache is keyed on a deterministic hash of your query key.
579- By default, query results become **stale** immediately after a successful fetch. This can be configured using the `staleTime` option at both the global and query-level.
580- Stale queries are automatically refetched whenever their **query keys change (this includes variables used in query key tuples)**, when they are freshly mounted from not having any instances on the page, or when they are refetched via the query cache manually.
581- Though a query result may be stale, query results are by default **always** _cached_ **when in use**.
582- If and when a query is no longer being used, it becomes **inactive** and by default is cached in the background for **5 minutes**. This time can be configured using the `cacheTime` option at both the global and query-level.
583- After a query is inactive for the `cacheTime` specified (defaults to 5 minutes), the query is deleted and garbage collected.
584
585<details>
586 <summary>A more detailed example of the caching lifecycle</summary>
587
588Let's assume we are using the default `cacheTime` of **5 minutes** and the default `staleTime` of `0`.
589
590- A new instance of `useQuery('todos', fetchTodos)` mounts.
591 - Since no other queries have been made with this query + variable combination, this query will show a hard loading state and make a network request to fetch the data.
592 - It will then cache the data using `'todos'` and `fetchTodos` as the unique identifiers for that cache.
593 - A stale invalidation is scheduled using the `staleTime` option as a delay (defaults to `0`, or immediately).
594- A second instance of `useQuery('todos', fetchTodos)` mounts elsewhere.
595 - Because this exact data exist in the cache from the first instance of this query, that data is immediately returned from the cache.
596- Both instances of the `useQuery('todos', fetchTodos)` query are unmounted and no longer in use.
597 - Since there are no more active instances to this query, a cache timeout is set using `cacheTime` to delete and garbage collect the query (defaults to **5 minutes**).
598- No more instances of `useQuery('todos', fetchTodos)` appear within **5 minutes**.
599 - This query and its data are deleted and garbage collected.
600
601</details>
602
603## Paginated Queries with `usePaginatedQuery`
604
605Rendering paginated data is a very common UI pattern to avoid overloading bandwidth or even your UI. React Query exposes a `usePaginatedQuery` that is very similar to `useQuery` that helps with this very scenario.
606
607Consider the following example where we would ideally want to increment a pageIndex (or cursor) for a query. If we were to use `useQuery`, it would technically work fine, but the UI would jump in and out of the `success` and `loading` states as different queries are created and destroyed for each page or cursor. By using `usePaginatedQuery` we get a few new things:
608
609- Instead of `data`, you should use `resolvedData` instead. This is the data from the last known successful query result. As new page queries resolve, `resolvedData` remains available to show the last page's data while a new page is requested. When the new page data is received, `resolvedData` get's updated to the new page's data.
610- If you specifically need the data for the exact page being requested, `latestData` is available. When the desired page is being requested, `latestData` will be `undefined` until the query resolves, then it will get updated with the latest pages data result.
611
612```js
613function Todos() {
614 const [page, setPage] = React.useState(0)
615
616 const fetchProjects = (key, page = 0) => fetch('/api/projects?page=' + page)
617
618 const {
619 status,
620 resolvedData,
621 latestData,
622 error,
623 isFetching,
624 } = usePaginatedQuery(['projects', page], fetchProjects)
625
626 return (
627 <div>
628 {status === 'loading' ? (
629 <div>Loading...</div>
630 ) : status === 'error' ? (
631 <div>Error: {error.message}</div>
632 ) : (
633 // `resolvedData` will either resolve to the latest page's data
634 // or if fetching a new page, the last successful page's data
635 <div>
636 {resolvedData.projects.map(project => (
637 <p key={project.id}>{project.name}</p>
638 ))}
639 </div>
640 )}
641 <span>Current Page: {page + 1}</span>
642 <button
643 onClick={() => setPage(old => Math.max(old - 1, 0))}
644 disabled={page === 0}
645 >
646 Previous Page
647 </button>{' '}
648 <button
649 onClick={() =>
650 // Here, we use `latestData` so the Next Page
651 // button isn't relying on potentially old data
652 setPage(old => (!latestData || !latestData.hasMore ? old : old + 1))
653 }
654 disabled={!latestData || !latestData.hasMore}
655 >
656 Next Page
657 </button>
658 {// Since the last page's data potentially sticks around between page requests,
659 // we can use `isFetching` to show a background loading
660 // indicator since our `status === 'loading'` state won't be triggered
661 isFetching ? <span> Loading...</span> : null}{' '}
662 </div>
663 )
664}
665```
666
667## Load-More & Infinite-Scroll with `useInfiniteQuery`
668
669Rendering lists that can additively "load more" data onto an existing set of data or "infinite scroll" is also a very common UI pattern. React Query supports a useful version of `useQuery` called `useInfiniteQuery` for querying these types of lists.
670
671When using `useInfiniteQuery`, you'll notice a few things are different:
672
673- `data` is now an array of arrays that contain query group results, instead of the query results themselves
674- A `fetchMore` function is now available
675- A `getFetchMore` option is available for both determining if there is more data to load and the information to fetch it. This information is supplied as an additional parameter in the query function (which can optionally be overridden when calling the `fetchMore` function)
676- A `canFetchMore` boolean is now available and is `true` if `getFetchMore` returns a truthy value
677- An `isFetchingMore` boolean is now available to distinguish between a background refresh state and a loading more state
678
679### Example
680
681Let's assume we have an API that returns pages of `projects` 3 at a time based on a `cursor` index along with a cursor that can be used to fetch the next group of projects
682
683```js
684fetch('/api/projects?cursor=0')
685// { data: [...], nextCursor: 3}
686fetch('/api/projects?cursor=3')
687// { data: [...], nextCursor: 6}
688fetch('/api/projects?cursor=6')
689// { data: [...], nextCursor: 9}
690fetch('/api/projects?cursor=9')
691// { data: [...] }
692```
693
694With this information, we can create a "Load More" UI by:
695
696- Waiting for `useInfiniteQuery` to request the first group of data by default
697- Returning the information for the next query in `getFetchMore`
698- Calling `fetchMore` function
699
700> Note: It's very important you do not call `fetchMore` with arguments unless you want them to override the `fetchMoreInfo` data returned from the `getFetchMore` function. eg. Do not do this: `<button onClick={fetchMore} />` as this would send the onClick event to the `fetchMore` function.
701
702```js
703import { useInfiniteQuery } from 'react-query'
704
705function Projects() {
706 const fetchProjects = (key, cursor = 0) =>
707 fetch('/api/projects?cursor=' + cursor)
708
709 const {
710 status,
711 data,
712 isFetching,
713 isFetchingMore,
714 fetchMore,
715 canFetchMore,
716 } = useInfiniteQuery('projects', fetchProjects, {
717 getFetchMore: (lastGroup, allGroups) => lastGroup.nextCursor,
718 })
719
720 return status === 'loading' ? (
721 <p>Loading...</p>
722 ) : status === 'error' ? (
723 <p>Error: {error.message}</p>
724 ) : (
725 <>
726 {data.map((group, i) => (
727 <React.Fragment key={i}>
728 {group.projects.map(project => (
729 <p key={project.id}>{project.name}</p>
730 ))}
731 </React.Fragment>
732 ))}
733 <div>
734 <button
735 onClick={() => fetchMore()}
736 disabled={!canFetchMore || isFetchingMore}
737 >
738 {isFetchingMore
739 ? 'Loading more...'
740 : canFetchMore
741 ? 'Load More'
742 : 'Nothing more to load'}
743 </button>
744 </div>
745 <div>{isFetching && !isFetchingMore ? 'Fetching...' : null}</div>
746 </>
747 )
748}
749```
750
751### What happens when an infinite query needs to be refetched?
752
753When an infinite query becomes `stale` and needs to be refetched, each group is fetched `sequentially`, starting from the first one. This ensures that even if the underlying data is mutated we're not using stale cursors and potentially getting duplicates or skipping records. If an infinite query's results are ever removed from the cache, the pagination restarts at the initial state with only the initial group being requested.
754
755### What if I need to pass custom information to my query function?
756
757By default, the info returned from `getFetchMore` will be supplied to the query function, but in some cases, you may want to override this. You can pass custom variables to the `fetchMore` function which will override the default info like so:
758
759```js
760function Projects() {
761 const fetchProjects = (key, cursor = 0) =>
762 fetch('/api/projects?cursor=' + cursor)
763
764 const {
765 status,
766 data,
767 isFetching,
768 isFetchingMore,
769 fetchMore,
770 canFetchMore,
771 } = useInfiniteQuery('projects', fetchProjects, {
772 getFetchMore: (lastGroup, allGroups) => lastGroup.nextCursor,
773 })
774
775 // Pass your own custom fetchMoreInfo
776 const skipToCursor50 = () => fetchMore(50)
777}
778```
779
780## Scroll Restoration
781
782Out of the box, "scroll restoration" for all queries (including paginated and infinite queries) Just Works™️ in React Query. The reason for this is that query results are cached and able to be retrieved synchronously when a query is rendered. As long as your queries are being cached long enough (the default time is 5 minutes) and have not been garbage collected, scroll restoration will work out of the box all the time.
783
784## Manual Querying
785
786If you ever want to disable a query from automatically running, you can use the `manual = true` option. When `manual` is set to true:
787
788- The query will start in the `status === 'success'` state
789- The query will not automatically fetch on mount
790- The query will not automatically refetch due to rerenders, new instances appearing, or changes to its query key or variables.
791
792> Pro Tip #1: Because manual queries start in the `status === 'success'` state, you should consider supplying an `initialData` option to pre-populate the cache or similarly use a default parameter value when destructuring the query result
793
794> Pro Tip #2: Don't use `manual` for dependent queries. Use [Dependent Queries](#dependent-queries) instead!
795
796```js
797function Todos() {
798 const { status, data, error, refetch, isFetching } = useQuery(
799 'todos',
800 fetchTodoList,
801 {
802 manual: true,
803 initialData: [],
804 }
805 )
806
807 return (
808 <>
809 <button onClick={() => refetch()}>Fetch Todos</button>
810
811 {status === 'loading' ? (
812 <span>Loading...</span>
813 ) : status === 'error' ? (
814 <span>Error: {error.message}</span>
815 ) : (
816 // `status === 'success'` will be the initial state, so we need
817 // account for our initial data (an empty array)
818 <>
819 <ul>
820 {!data.length
821 ? 'No todos yet...'
822 : data.map(todo => <li key={todo.id}>{todo.title}</li>)}
823 </ul>
824 <div>{isFetching ? 'Fetching...' : null}</div>
825 </>
826 )}
827 </>
828 )
829}
830```
831
832## Retries
833
834When a `useQuery` query fails (the function throws an error), React Query will automatically retry the query if that query's request has not reached the max number of consecutive retries (defaults to `3`) or a function is provided to determine if a retry is allowed.
835
836You can configure retries both on a global level and an individual query level.
837
838- Setting `retry = false` will disable retries.
839- Setting `retry = 6` will retry failing requests 6 times before showing the final error thrown by the function.
840- Setting `retry = true` will infinitely retry failing requests.
841- Setting `retry = (failureCount, error) => ...` allows for custom logic based on why the request failed.
842
843```js
844import { useQuery } from 'react-query'
845
846// Make specific query retry a certain number of times
847const { status, data, error } = useQuery(['todos', 1], fetchTodoListPage, {
848 retry: 10, // Will retry failed requests 10 times before displaying an error
849})
850```
851
852## Retry Delay
853
854By default, retries in React Query do not happen immediately after a request fails. As is standard, a back-off delay is gradually applied to each retry attempt.
855
856The default `retryDelay` is set to double (starting at `1000`ms) with each attempt, but not exceed 30 seconds:
857
858```js
859// Configure for all queries
860import { ReactQueryConfigProvider } from 'react-query'
861
862const queryConfig = {
863 retryDelay: attemptIndex => Math.min(1000 * 2 ** attemptIndex, 30000),
864}
865
866function App() {
867 return (
868 <ReactQueryConfigProvider config={queryConfig}>
869 ...
870 </ReactQueryConfigProvider>
871 )
872}
873```
874
875Though it is not recommended, you can obviously override the `retryDelay` function/integer in both the Provider and individual query options. If set to an integer instead of a function the delay will always be the same amount of time:
876
877```js
878const { status, data, error } = useQuery('todos', fetchTodoList, {
879 retryDelay: 1000, // Will always wait 1000ms to retry, regardless of how many retries
880})
881```
882
883## Prefetching
884
885If you're lucky enough, you may know enough about what your users will do to be able to prefetch the data they need before it's needed! If this is the case, then you're in luck. You can either use the `prefetchQuery` function to prefetch the results of a query to be placed into the cache:
886
887```js
888import { queryCache } from 'react-query'
889
890const prefetchTodos = async () => {
891 const queryData = await queryCache.prefetchQuery('todos', () =>
892 fetch('/todos')
893 )
894 // The results of this query will be cached like a normal query
895}
896```
897
898The next time a `useQuery` instance is used for a prefetched query, it will use the cached data! If no instances of `useQuery` appear for a prefetched query, it will be deleted and garbage collected after the time specified in `cacheTime`.
899
900Alternatively, if you already have the data for your query synchronously available, you can use the [Query Cache's `setQueryData` method](#querycachesetquerydata) to directly add or update a query's cached result
901
902## Initial Data
903
904There may be times when you already have the initial data for a query synchronously available in your app. If and when this is the case, you can use the `config.initialData` option to set the initial data for a query and skip the first round of fetching!
905
906When providing an `initialData` value that is anything other than `undefined`:
907
908- The query `status` will initialize as `success` instead of `loading`
909- The query's `isStale` property will initialize as `true` instead of false
910- The query will not automatically fetch until it is invalidated somehow (eg. window refocus, queryCache refetching, etc)
911
912```js
913function Todos() {
914 const queryInfo = useQuery('todos', () => fetch('/todos'), {
915 initialData: initialTodos,
916 })
917}
918```
919
920## Initial Data Function
921
922If the process for accessing a query's initial data is intensive or just not something you want to perform on every render, you can pass a function as the `initialData` value. This function will be executed only once when the query is initialized, saving you precious memory and CPU:
923
924```js
925function Todos() {
926 const queryInfo = useQuery('todos', () => fetch('/todos'), {
927 initialData: () => {
928 return getExpensiveTodos()
929 },
930 })
931}
932```
933
934## Initial Data from Cache
935
936In some circumstances, you may be able to provide the initial data for a query from the cached result of another. A good example of this would be searching the cached data from a todos list query for an individual todo item, then using that as the initial data for your individual todo query:
937
938```js
939function Todo({ todoId }) {
940 const queryInfo = useQuery(['todo', todoId], () => fetch('/todos'), {
941 initialData: () => {
942 // Use a todo from the 'todos' query as the initial data for this todo query
943 return queryCache.getQueryData('todos')?.find(d => d.id === todoId)
944 },
945 })
946}
947```
948
949Most of the time, this pattern works well, but if the source query you're using to look up the initial data from is old, you may not want to use the data at all and just fetch from the server. To make this decision easier, you can use the `queryCache.getQuery` method instead to get more information about the source query, including an `updatedAt` timestamp you can use to decide if the query is "fresh" enough for your needs:
950
951```js
952function Todo({ todoId }) {
953 const queryInfo = useQuery(['todo', todoId], () => fetch('/todos'), {
954 initialData: () => {
955 // Get the query object
956 const query = queryCache.getQuery('todos')
957
958 // If the query exists and has data that is no older than 10 seconds...
959 if (query && Date.now() - query.updatedAt <= 10 * 1000) {
960 // return the individual todo
961 return query.state.data.find(d => d.id === todoId)
962 }
963
964 // Otherwise, return undefined and let it fetch!
965 },
966 })
967}
968```
969
970## SSR & Initial Data
971
972When using SSR (server-side-rendering) with React Query there are a few things to note:
973
974- Query caches are not written to memory during SSR. This is outside of the scope of React Query and easily leads to out-of-sync data when used with frameworks like Next.js or other SSR strategies.
975- Queries rendered on the server will by default use the `initialData` of an unfetched query. This means that by default, `data` will be set to `undefined`. To get around this in SSR, you can either pre-seed a query's cache data using the `config.initialData` option:
976
977```js
978const { status, data, error } = useQuery('todos', fetchTodoList, {
979 initialData: [{ id: 0, name: 'Implement SSR!' }],
980})
981
982// data === [{ id: 0, name: 'Implement SSR!'}]
983```
984
985Or, alternatively you can just destructure from `undefined` in your query results:
986
987```js
988const { status, data = [{ id: 0, name: 'Implement SSR!' }], error } = useQuery(
989 'todos',
990 fetchTodoList
991)
992```
993
994The query's state will still reflect that it is stale and has not been fetched yet, and once mounted, it will continue as normal and request a fresh copy of the query result.
995
996## Suspense Mode
997
998React Query can also be used with React's new Suspense for Data Fetching API's. To enable this mode, you can set either the global or query level config's `suspense` option to `true`.
999
1000Global configuration:
1001
1002```js
1003// Configure for all queries
1004import { ReactQueryConfigProvider } from 'react-query'
1005
1006const queryConfig = {
1007 suspense: true,
1008}
1009
1010function App() {
1011 return (
1012 <ReactQueryConfigProvider config={queryConfig}>
1013 ...
1014 </ReactQueryConfigProvider>
1015 )
1016}
1017```
1018
1019Query configuration:
1020
1021```js
1022import { useQuery } from 'react-query'
1023
1024// Enable for an individual query
1025useQuery(queryKey, queryFn, { suspense: true })
1026```
1027
1028When using suspense mode, `status` states and `error` objects are not needed and are then replaced by usage of the `React.Suspense` component (including the use of the `fallback` prop and React error boundaries for catching errors). Please see the [Suspense Example](https://codesandbox.io/s/github/tannerlinsley/react-query/tree/master/examples/suspense) for more information on how to set up suspense mode.
1029
1030In addition to queries behaving differently in suspense mode, mutations also behave a bit differently. By default, instead of supplying the `error` variable when a mutation fails, it will be thrown during the next render of the component it's used in and propagate to the nearest error boundary, similar to query errors. If you wish to disable this, you can set the `useErrorBoundary` option to `false`. If you wish that errors are not thrown at all, you can set the `throwOnError` option to `false` as well!
1031
1032## Fetch-on-render vs Fetch-as-you-render
1033
1034Out of the box, React Query in `suspense` mode works really well as a **Fetch-on-render** solution with no additional configuration. However, if you want to take it to the next level and implement a `Fetch-as-you-render` model, we recommend implementing [Prefetching](#prefetching) on routing and/or user interactions events to initialize queries before they are needed.
1035
1036## Canceling Query Requests
1037
1038By default, queries that become inactive before their promises are resolved are simply ignored instead of canceled. Why is this?
1039
1040- For most applications, ignoring out-of-date queries is sufficient.
1041- Cancellation APIs may not be available for every query function.
1042- If cancellation APIs are available, they typically vary in implementation between utilities/libraries (eg. Fetch vs Axios vs XMLHttpRequest).
1043
1044But don't worry! If your queries are high-bandwidth or potentially very expensive to download, React Query exposes a generic way to **cancel** query requests using a cancellation token or other related API. To integrate with this feature, attach a `cancel` function to the promise returned by your query that implements your request cancellation. When a query becomes out-of-date or inactive, this `promise.cancel` function will be called (if available):
1045
1046Using `axios`:
1047
1048```js
1049import { CancelToken } from 'axios'
1050
1051const query = useQuery('todos', () => {
1052 // Create a new CancelToken source for this request
1053 const source = CancelToken.source()
1054
1055 const promise = axios.get('/todos', {
1056 // Pass the source token to your request
1057 cancelToken: source.token,
1058 })
1059
1060 // Cancel the request if React Query calls the `promise.cancel` method
1061 promise.cancel = () => {
1062 source.cancel('Query was cancelled by React Query')
1063 }
1064
1065 return promise
1066})
1067```
1068
1069Using `fetch`:
1070
1071```js
1072const query = useQuery('todos', () => {
1073 // Create a new AbortController instance for this request
1074 const controller = new AbortController()
1075 // Get the abortController's signal
1076 const signal = controller.signal
1077
1078 const promise = fetch('/todos', {
1079 method: 'get',
1080 // Pass the signal to your request
1081 signal,
1082 })
1083
1084 // Cancel the request if React Query calls the `promise.cancel` method
1085 promise.cancel = controller.abort
1086
1087 return promise
1088})
1089```
1090
1091# Mutations
1092
1093Unlike queries, mutations are typically used to create/update/delete data or perform server side-effects. For this purpose, React Query exports a `useMutation` hook.
1094
1095## Basic Mutations
1096
1097Assuming the server implements a ping mutation, that returns "pong" string, here's an example of the most basic mutation:
1098
1099```js
1100const PingPong = () => {
1101 const [mutate, { status, data, error }] = useMutation(pingMutation)
1102
1103 const onPing = async () => {
1104 try {
1105 const data = await mutate()
1106 console.log(data)
1107 // { ping: 'pong' }
1108 } catch {
1109 // Uh oh, something went wrong
1110 }
1111 }
1112 return <button onClick={onPing}>Ping</button>
1113}
1114```
1115
1116Mutations without variables are not that useful, so let's add some variables to closer match reality.
1117
1118## Mutation Variables
1119
1120To pass `variables` to your `mutate` function, call `mutate` with an object.
1121
1122```js
1123// Notice how the fetcher function receives an object containing
1124// all possible variables
1125const createTodo = ({ title }) => {
1126 /* trigger an http request */
1127}
1128
1129const CreateTodo = () => {
1130 const [title, setTitle] = useState('')
1131 const [mutate] = useMutation(createTodo)
1132
1133 const onCreateTodo = async e => {
1134 // Prevent the form from refreshing the page
1135 e.preventDefault()
1136
1137 try {
1138 await mutate({ title })
1139 // Todo was successfully created
1140 } catch (error) {
1141 // Uh oh, something went wrong
1142 }
1143 }
1144
1145 return (
1146 <form onSubmit={onCreateTodo}>
1147 <input
1148 type="text"
1149 value={title}
1150 onChange={e => setTitle(e.target.value)}
1151 />
1152 <br />
1153 <button type="submit">Create Todo</button>
1154 </form>
1155 )
1156}
1157```
1158
1159Even with just variables, mutations aren't all that special, but when used with the `onSuccess` option, the [Query Cache's `refetchQueries` method](#querycacherefetchqueries) method and the [Query Cache's `setQueryData` method](#querycachesetquerydata), mutations become a very powerful tool.
1160
1161Note that since version 1.1.0, the `mutate` function is no longer called synchronously so you cannot use it in an event callback. If you need to access the event in `onSubmit` you need to wrap `mutate` in another function. This is due to [React event pooling](https://reactjs.org/docs/events.html#event-pooling).
1162
1163```js
1164// This will not work
1165const CreateTodo = () => {
1166 const [mutate] = useMutation(event => {
1167 event.preventDefault()
1168 fetch('/api', new FormData(event.target))
1169 })
1170
1171 return (
1172 <form onSubmit={mutate}>...</form>
1173 )
1174}
1175
1176// This will work
1177const CreateTodo = () => {
1178 const [mutate] = useMutation(formData => {
1179 fetch('/api', formData)
1180 })
1181 const onSubmit = event => {
1182 event.preventDefault()
1183 mutate(new FormData(event.target))
1184 }
1185
1186 return (
1187 <form onSubmit={onSubmit}>...</form>
1188 )
1189}
1190```
1191
1192## Invalidate and Refetch Queries from Mutations
1193
1194When a mutation succeeds, it's likely that other queries in your application need to update. Where other libraries that use normalized caches would attempt to update local queries with the new data imperatively, React Query helps you to avoid the manual labor that comes with maintaining normalized caches and instead prescribes **atomic updates and refetching** instead of direct cache manipulation.
1195
1196For example, assume we have a mutation to post a new todo:
1197
1198```js
1199const [mutate] = useMutation(postTodo)
1200```
1201
1202When a successful `postTodo` mutation happens, we likely want all `todos` queries to get refetched to show the new todo item. To do this, you can use `useMutation`'s `onSuccess` options and the `queryCache`'s `refetchQueries`:
1203
1204```js
1205import { useMutation, queryCache } from 'react-query'
1206
1207// When this mutation succeeds, refetch any queries with the `todos` or `reminders` query key
1208const [mutate] = useMutation(addTodo, {
1209 onSuccess: () => {
1210 queryCache.refetchQueries('todos')
1211 queryCache.refetchQueries('reminders')
1212 },
1213})
1214
1215mutate(todo)
1216
1217// The 3 queries below will be refetched when the mutation above succeeds
1218const todoListQuery = useQuery('todos', fetchTodoList)
1219const todoListQuery = useQuery(['todos', { page: 1 }], fetchTodoList)
1220const remindersQuery = useQuery('reminders', fetchReminders)
1221```
1222
1223You can even refetch queries with specific variables by passing a more specific query key to the `refetchQueries` method:
1224
1225```js
1226const [mutate] = useMutation(addTodo, {
1227 onSuccess: () => {
1228 queryCache.refetchQueries(['todos', { type: 'done' }])
1229 },
1230})
1231
1232mutate(todo)
1233
1234// The query below will be refetched when the mutation above succeeds
1235const todoListQuery = useQuery(['todos', { type: 'done' }], fetchTodoList)
1236// However, the following query below will NOT be refetched
1237const todoListQuery = useQuery('todos', fetchTodoList)
1238```
1239
1240The `refetchQueries` API is very flexible, so even if you want to **only** refetch `todos` queries that don't have any more variables or subkeys, you can pass an `exact: true` option to the `refetchQueries` method:
1241
1242```js
1243const [mutate] = useMutation(addTodo, {
1244 onSuccess: () => {
1245 queryCache.refetchQueries('todos', { exact: true })
1246 },
1247})
1248
1249mutate(todo)
1250
1251// The query below will be refetched when the mutation above succeeds
1252const todoListQuery = useQuery(['todos'], fetchTodoList)
1253// However, the following query below will NOT be refetched
1254const todoListQuery = useQuery(['todos', { type: 'done' }], fetchTodoList)
1255```
1256
1257If you find yourself wanting **even more** granularity, you can pass a predicate function to the `refetchQueries` method. This function will receive each query object from the queryCache and allow you to return `true` or `false` for whether you want to refetch that query:
1258
1259```js
1260const [mutate] = useMutation(addTodo, {
1261 onSuccess: () => {
1262 queryCache.refetchQueries(
1263 query => query.queryKey[0] === 'todos' && query.queryKey[1]?.version >= 10
1264 )
1265 },
1266})
1267
1268mutate(todo)
1269
1270// The query below will be refetched when the mutation above succeeds
1271const todoListQuery = useQuery(['todos', { version: 20 }], fetchTodoList)
1272// The query below will be refetched when the mutation above succeeds
1273const todoListQuery = useQuery(['todos', { version: 10 }], fetchTodoList)
1274// However, the following query below will NOT be refetched
1275const todoListQuery = useQuery(['todos', { version: 5 }], fetchTodoList)
1276```
1277
1278If you prefer that the promise returned from `mutate()` only resolves **after** the `onSuccess` callback, you can return a promise in the `onSuccess` callback:
1279
1280```js
1281const [mutate] = useMutation(addTodo, {
1282 onSuccess: () =>
1283 // return a promise!
1284 queryCache.refetchQueries(
1285 query => query.queryKey[0] === 'todos' && query.queryKey[1]?.version >= 10
1286 ),
1287})
1288
1289const run = async () => {
1290 try {
1291 await mutate(todo)
1292 console.log('I will only log after onSuccess is done!')
1293 } catch {}
1294}
1295```
1296
1297If you would like to refetch queries on error or even regardless of a mutation's success or error, you can use the `onError` or `onSettled` callbacks:
1298
1299```js
1300const [mutate] = useMutation(addTodo, {
1301 onError: error => {
1302 // Refetch queries or more...
1303 },
1304 onSettled: (data, error) => {
1305 // Refetch queries or more...
1306 },
1307})
1308
1309mutate(todo)
1310```
1311
1312You might find that you want to **add on** to some of the `useMutation`'s options at the time of calling `mutate`. To do that, you can provide any of the same options to the `mutate` function after your mutation variable. Supported option overrides include:
1313
1314- `onSuccess` - Will be fired before the `useMutation`-level `onSuccess` handler
1315- `onError` - Will be fired before the `useMutation`-level `onError` handler
1316- `onSettled` - Will be fired before the `useMutation`-level `onSettled` handler
1317- `throwOnError`
1318
1319```js
1320const [mutate] = useMutation(addTodo, {
1321 onSuccess: (data, mutationVariables) => {
1322 // I will fire second
1323 },
1324 onSettled: (data, error, mutationVariables) => {
1325 // I will fire second
1326 },
1327 onError: (error, mutationVariables) => {
1328 // I will fire second
1329 },
1330})
1331
1332mutate(todo, {
1333 onSuccess: (data, mutationVariables) => {
1334 // I will fire first!
1335 },
1336 onSettled: (data, error, mutationVariables) => {
1337 // I will fire first!
1338 },
1339 onError: (error, mutationVariables) => {
1340 // I will fire first!
1341 },
1342 throwOnError: true,
1343})
1344```
1345
1346## Query Updates from Mutations
1347
1348When dealing with mutations that **update** objects on the server, it's common for the new object to be automatically returned in the response of the mutation. Instead of refetching any queries for that item and wasting a network call for data we already have, we can take advantage of the object returned by the mutation function and update the existing query with the new data immediately using the [Query Cache's `setQueryData`](#querycachesetquerydata) method:
1349
1350```js
1351const [mutate] = useMutation(editTodo, {
1352 onSuccess: data => queryCache.setQueryData(['todo', { id: 5 }], data),
1353})
1354
1355mutate({
1356 id: 5,
1357 name: 'Do the laundry',
1358})
1359
1360// The query below will be updated with the response from the
1361// successful mutation
1362const { status, data, error } = useQuery(['todo', { id: 5 }], fetchTodoByID)
1363```
1364
1365You might want to tight the `onSuccess` logic into a reusable mutation, for that you can
1366create a custom hook like this:
1367
1368```js
1369const useMutateTodo = () => {
1370 return useMutate(editTodo, {
1371 // Notice the second argument is the variables object that the `mutate` function receives
1372 onSuccess: (data, variables) => {
1373 queryCache.setQueryData(['todo', { id: variables.id }], data)
1374 },
1375 })
1376}
1377```
1378
1379## Resetting Mutation State
1380
1381It's sometimes the case that you need to clear the `error` or `data` of a mutation request. To do this, you can use the `reset` function to handle this:
1382
1383```js
1384const CreateTodo = () => {
1385 const [title, setTitle] = useState('')
1386 const [mutate, { error, reset }] = useMutation(createTodo)
1387
1388 const onCreateTodo = async e => {
1389 e.preventDefault()
1390 await mutate({ title })
1391 }
1392
1393 return (
1394 <form onSubmit={onCreateTodo}>
1395 {error && <h5 onClick={() => reset()}>{error}</h5>}
1396 <input
1397 type="text"
1398 value={title}
1399 onChange={e => setTitle(e.target.value)}
1400 />
1401 <br />
1402 <button type="submit">Create Todo</button>
1403 </form>
1404 )
1405}
1406```
1407
1408## Manually or Optimistically Setting Query Data
1409
1410In rare circumstances, you may want to manually update a query's response with a custom value. To do this, you can again use the [Query Cache's `setQueryData`](#querycachesetquerydata) method:
1411
1412> **It's important to understand** that when you manually or optimistically update a query's data value, the potential that you display out-of-sync data to your users is very high. It's recommended that you only do this if you plan to refetch the query very soon or perform a mutation to "commit" your manual changes (and also roll back your eager update if the refetch or mutation fails).
1413
1414```js
1415// Full replacement
1416queryCache.setQueryData(['todo', { id: 5 }], newTodo)
1417
1418// or functional update
1419queryCache.setQueryData(['todo', { id: 5 }], previous => ({
1420 ...previous,
1421 type: 'done',
1422}))
1423```
1424
1425## Optimistic Updates with Automatic Rollback for Failed Mutations
1426
1427When you optimistically update your state before performing a mutation, there is a non-zero chance that the mutation will fail. In most cases, you can just trigger a refetch for your optimistic queries to revert them to their true server state. In some circumstances though, refetching may not work correctly and the mutation error could represent some type of server issue that won't make it possible to refetch. In this event, you can instead choose to rollback your update.
1428
1429To do this, `useMutation`'s `onMutate` handler option allows you to return a value that will later be passed to both `onError` and `onSettled` handlers as the last argument. In most cases, it is most useful to pass a rollback function.
1430
1431### Updating a list of todos when adding a new todo
1432
1433```js
1434useMutation(updateTodo, {
1435 // When mutate is called:
1436 onMutate: newTodo => {
1437 // Snapshot the previous value
1438 const previousTodos = queryCache.getQueryData('todos')
1439
1440 // Optimistically update to the new value
1441 queryCache.setQueryData('todos', old => [...old, newTodo])
1442
1443 // Return the snapshotted value
1444 return () => queryCache.setQueryData('todos', previousTodos)
1445 },
1446 // If the mutation fails, use the value returned from onMutate to roll back
1447 onError: (err, newTodo, rollback) => rollback(),
1448 // Always refetch after error or success:
1449 onSettled: () => {
1450 queryCache.refetchQueries('todos')
1451 },
1452})
1453```
1454
1455### Updating a single todo
1456
1457```js
1458useMutation(updateTodo, {
1459 // When mutate is called:
1460 onMutate: newTodo => {
1461 // Snapshot the previous value
1462 const previousTodo = queryCache.getQueryData(['todos', newTodo.id], newTodo)
1463
1464 // Optimistically update to the new value
1465 queryCache.setQueryData(['todos', newTodo.id], newTodo)
1466
1467 // Return a rollback function
1468 return () => queryCache.setQueryData(['todos', newTodo.id], previousTodo)
1469 },
1470 // If the mutation fails, use the rollback function we returned above
1471 onError: (err, newTodo, rollback) => rollback(),
1472 // Always refetch after error or success:
1473 onSettled: () => {
1474 queryCache.refetchQueries(['todos', newTodo.id])
1475 },
1476})
1477```
1478
1479You can also use the `onSettled` function in place of the separate `onError` and `onSuccess` handlers if you wish:
1480
1481```js
1482useMutation(updateTodo, {
1483 // ...
1484 onSettled: (newTodo, error, variables, rollback) => {
1485 if (error) {
1486 rollback()
1487 }
1488 },
1489})
1490```
1491
1492# Displaying Background Fetching Loading States
1493
1494A query's `status === 'loading'` state is sufficient enough to show the initial hard-loading state for a query, but sometimes you may want to display an additional indicator that a query is refetching in the background. To do this, queries also supply you with an `isFetching` boolean that you can use to show that it's in a fetching state, regardless of the state of the `status` variable:
1495
1496```js
1497function Todos() {
1498 const { status, data: todos, error, isFetching } = useQuery(
1499 'todos',
1500 fetchTodos
1501 )
1502
1503 return status === 'loading' ? (
1504 <span>Loading...</span>
1505 ) : status === 'error' ? (
1506 <span>Error: {error.message}</span>
1507 ) : (
1508 <>
1509 {isFetching ? <div>Refreshing...</div> : null}
1510
1511 <div>
1512 {todos.map(todo => (
1513 <Todo todo={todo} />
1514 ))}
1515 </div>
1516 </>
1517 )
1518}
1519```
1520
1521# Displaying Global Background Fetching Loading State
1522
1523In addition to individual query loading states, if you would like to show a global loading indicator when **any** queries are fetching (including in the background), you can use the `useIsFetching` hook:
1524
1525```js
1526import { useIsFetching } from 'react-query'
1527
1528function GlobalLoadingIndicator() {
1529 const isFetching = useIsFetching()
1530
1531 return isFetching ? (
1532 <div>Queries are fetching in the background...</div>
1533 ) : null
1534}
1535```
1536
1537# Window-Focus Refetching
1538
1539If a user leaves your application and returns to stale data, you may want to trigger an update in the background to update any stale queries. Thankfully, **React Query does this automatically for you**, but if you choose to disable it, you can use the `ReactQueryConfigProvider`'s `refetchAllOnWindowFocus` option to disable it:
1540
1541```js
1542const queryConfig = { refetchAllOnWindowFocus: false }
1543
1544function App() {
1545 return (
1546 <ReactQueryConfigProvider config={queryConfig}>
1547 ...
1548 </ReactQueryConfigProvider>
1549 )
1550}
1551```
1552
1553## Custom Window Focus Event
1554
1555In rare circumstances, you may want to manage your own window focus events that trigger React Query to revalidate. To do this, React Query provides a `setFocusHandler` function that supplies you the callback that should be fired when the window is focused and allows you to set up your own events. When calling `setFocusHandler`, the previously set handler is removed (which in most cases will be the default handler) and your new handler is used instead. For example, this is the default handler:
1556
1557```js
1558setFocusHandler(handleFocus => {
1559 // Listen to visibillitychange and focus
1560 if (typeof window !== 'undefined' && window.addEventListener) {
1561 window.addEventListener('visibilitychange', handleFocus, false)
1562 window.addEventListener('focus', handleFocus, false)
1563 }
1564
1565 return () => {
1566 // Be sure to unsubscribe if a new handler is set
1567 window.removeEventListener('visibilitychange', handleFocus)
1568 window.removeEventListener('focus', handleFocus)
1569 }
1570})
1571```
1572
1573## Ignoring Iframe Focus Events
1574
1575A great use-case for replacing the focus handler is that of iframe events. Iframes present problems with detecting window focus by both double-firing events and also firing false-positive events when focusing or using iframes within your app. If you experience this, you should use an event handler that ignores these events as much as possible. I recommend [this one](https://gist.github.com/tannerlinsley/1d3a2122332107fcd8c9cc379be10d88)! It can be set up in the following way:
1576
1577```js
1578import { setFocusHandler } from 'react-query'
1579import onWindowFocus from './onWindowFocus' // The gist above
1580
1581setFocusHandler(onWindowFocus) // Boom!
1582```
1583
1584# Custom Query Key Serializers (Experimental)
1585
1586> **WARNING:** This is an advanced and experimental feature. There be dragons here. Do not change the Query Key Serializer unless you know what you are doing and are fine with encountering edge cases in React Query's API
1587
1588<details>
1589<summary>Show Me The Dragons!</summary>
1590
1591If you absolutely despise the default query key implementation, then please file an issue in this repo first. If you still believe you need something different, then you can choose to replace the default query key serializer with your own by using the `ReactQueryConfigProvider` hook's `queryKeySerializerFn` option:
1592
1593```js
1594const queryConfig = {
1595 queryKeySerializerFn: queryKey => {
1596 // Your custom logic here...
1597
1598 // Make sure object keys are sorted and all values are
1599 // serializable
1600 const queryFnArgs = getQueryArgs(queryKey)
1601
1602 // Hash the query key args to get a string
1603 const queryHash = hash(queryFnArgs)
1604
1605 // Return both the queryHash and normalizedQueryHash as a tuple
1606 return [queryHash, queryFnArgs]
1607 },
1608}
1609
1610function App() {
1611 return (
1612 <ReactQueryConfigProvider config={queryConfig}>
1613 ...
1614 </ReactQueryConfigProvider>
1615 )
1616}
1617```
1618
1619- `userQueryKey: any`
1620 - This is the queryKey passed in `useQuery` and all other public methods and utilities exported by React Query.
1621 - It may be a string or an array of serializable values
1622 - If a string is passed, it must be wrapped in an array when returned as the `queryFnArgs`
1623- `queryHash: string`
1624 - This must be a unique `string` representing the entire query key.
1625 - It must be stable and deterministic and should not change if things like the order of variables are changed or shuffled.
1626- `queryFnArgs: Array<any>`
1627 - This array will be spread into the query function arguments and should be the same format as the queryKey but be deterministically stable and should not change structure if the variables of the query stay the same, but change order within array position.
1628
1629> An additional `stableStringify` utility is also exported to help with stringifying objects to have sorted keys.
1630
1631### URL Query Key Serializer Example
1632
1633The example below shows how to build your own serializer for use with URLs and use it with React Query:
1634
1635```js
1636import { ReactQueryConfigProvider, stableStringify } from 'react-query'
1637
1638function urlQueryKeySerializer(queryKey) {
1639 // Deconstruct the url
1640 let [url, params = ''] = queryKey.split('?')
1641
1642 // Remove trailing slashes from the url to make an ID
1643 url = url.replace(/\/{1,}$/, '')
1644
1645 // Build the searchQuery object
1646 params.split('&').filter(Boolean)
1647
1648 // If there are search params, return a different key
1649 if (Object.keys(params).length) {
1650 let searchQuery = {}
1651
1652 params.forEach(param => {
1653 const [key, value] = param.split('=')
1654 searchQuery[key] = value
1655 })
1656
1657 // Use stableStringify to turn searchQuery into a stable string
1658 const searchQueryHash = stableStringify(searchQuery)
1659
1660 // Get the stable json object for the normalized key
1661 searchQuery = JSON.parse(searchQueryHash)
1662
1663 return [`${url}_${searchQueryHash}`, [url, searchQuery]]
1664 }
1665
1666 return [url, [url]]
1667}
1668
1669const queryConfig = {
1670 queryKeySerializerFn: urlQueryKeySerializer,
1671}
1672
1673function App() {
1674 return (
1675 <ReactQueryConfigProvider config={queryConfig}>
1676 ...
1677 </ReactQueryConfigProvider>
1678 )
1679}
1680
1681// Heck, you can even make your own custom useQueryHook!
1682
1683function useUrlQuery(url, options) {
1684 return useQuery(url, (url, params) =>
1685 axios
1686 .get(url, {
1687 params,
1688 })
1689 .then(res => res.data)
1690 )
1691}
1692
1693// Use it in your app!
1694
1695function Todos() {
1696 const todosQuery = useUrlQuery(`/todos`)
1697}
1698
1699function FilteredTodos({ status = 'pending' }) {
1700 const todosQuery = useUrlQuery(`/todos?status=pending`)
1701}
1702
1703function Todo({ id }) {
1704 const todoQuery = useUrlQuery(`/todos/${id}`)
1705}
1706
1707refetchQuery('/todos')
1708refetchQuery('/todos?status=pending')
1709refetchQuery('/todos/5')
1710```
1711
1712### Function Query Key Serializer Example
1713
1714The example below shows how to you build your own functional serializer and use it with React Query:
1715
1716```js
1717import { ReactQueryConfigProvider, stableStringify } from 'react-query'
1718
1719// A map to keep track of our function pointers
1720const functionSerializerMap = new Map()
1721
1722function functionQueryKeySerializer(queryKey) {
1723 if (!queryKey) {
1724 return []
1725 }
1726
1727 let queryFn = queryKey
1728 let variables
1729
1730 if (Array.isArray(queryKey)) {
1731 queryFn = queryKey[0]
1732 variables = queryKey[1]
1733 }
1734
1735 // Get or create an ID for the function pointer
1736 const queryGroupId =
1737 functionSerializerMap.get(queryFn) ||
1738 (() => {
1739 const id = Date.now()
1740 functionSerializerMap.set(queryFn, id)
1741 return id
1742 })()
1743
1744 const variablesIsObject = isObject(variables)
1745
1746 const variablesHash = variablesIsObject ? stableStringify(variables) : ''
1747
1748 const queryHash = `${queryGroupId}_${variablesHash}`
1749
1750 return [queryHash, queryGroupId, variablesHash, variables]
1751}
1752
1753const queryConfig = {
1754 queryKeySerializerFn: functionQueryKeySerializer,
1755}
1756
1757function App() {
1758 return (
1759 <ReactQueryConfigProvider config={queryConfig}>
1760 ...
1761 </ReactQueryConfigProvider>
1762 )
1763}
1764// Heck, you can even make your own custom useQueryHook!
1765
1766function useFunctionQuery(functionTuple, options) {
1767 const [queryFn, variables] = Array.isArray(functionTuple)
1768 ? functionTuple
1769 : [functionTuple]
1770 return useQuery(functionTuple, queryFn, options)
1771}
1772
1773// Use it in your app!
1774
1775function Todos() {
1776 const todosQuery = useFunctionQuery(getTodos)
1777}
1778
1779function FilteredTodos({ status = 'pending' }) {
1780 const todosQuery = useFunctionQuery([getTodos, { status }])
1781}
1782
1783function Todo({ id }) {
1784 const todoQuery = useFunctionQuery([getTodo, { id }])
1785}
1786
1787refetchQuery(getTodos)
1788refetchQuery([getTodos, { type: 'pending' }])
1789refetchQuery([getTodo, { id: 5 }])
1790```
1791
1792</details>
1793
1794# React Query Devtools
1795
1796React query has dedicated devtools! Visit the [React Query Devtools Github Repo](https://github.com/tannerlinsley/react-query-devtools) for information on how to install and use them!
1797
1798To see a demo, [check out the Sandbox example!](https://codesandbox.io/s/github/tannerlinsley/react-query/tree/master/examples/playground)
1799
1800[![React Query Header](https://github.com/tannerlinsley/react-query-devtools/raw/master/media/header.png)](https://github.com/tannerlinsley/react-query-devtools)
1801
1802# API
1803
1804## `useQuery`
1805
1806```js
1807const {
1808 status,
1809 data,
1810 error,
1811 isFetching,
1812 failureCount,
1813 refetch,
1814} = useQuery(queryKey, [, queryVariables], queryFn, {
1815 manual,
1816 retry,
1817 retryDelay,
1818 staleTime
1819 cacheTime,
1820 refetchInterval,
1821 refetchIntervalInBackground,
1822 refetchOnWindowFocus,
1823 onSuccess,
1824 onError,
1825 onSettled,
1826 suspense,
1827 initialData,
1828 refetchOnMount,
1829 queryFnParamsFilter
1830})
1831
1832// or using the object syntax
1833
1834const queryInfo = useQuery({
1835 queryKey,
1836 queryFn,
1837 variables,
1838 config
1839})
1840```
1841
1842### Options
1843
1844- `queryKey: String | [String, Variables: Object] | falsy | Function => queryKey`
1845 - **Required**
1846 - The query key to use for this query.
1847 - If a string is passed, it will be used as the query key.
1848 - If a `[String, Object]` tuple is passed, they will be serialized into a stable query key. See [Query Keys](#query-keys) for more information.
1849 - If a falsy value is passed, the query will be disabled and not run automatically.
1850 - If a function is passed, it should resolve to any other valid query key type. If the function throws, the query will be disabled and not run automatically.
1851 - The query will automatically update when this key changes (if the key is not falsy and if `manual` is not set to `true`).
1852 - `Variables: Object`
1853 - If a tuple with variables is passed, this object should be **serializable**.
1854 - Nested arrays and objects are supported.
1855 - The order of object keys is sorted to be stable before being serialized into the query key.
1856- `queryFn: Function(variables) => Promise(data/error)`
1857 - **Required**
1858 - The function that the query will use to request data.
1859 - Receives the following variables in the order that they are provided:
1860 - Query Key Variables
1861 - Optional Query Variables passed after the key and before the query function
1862 - Must return a promise that will either resolves data or throws an error.
1863- `manual: Boolean`
1864 - Set this to `true` to disable automatic refetching when the query mounts or changes query keys.
1865 - To refetch the query, use the `refetch` method returned from the `useQuery` instance.
1866- `retry: Boolean | Int | Function(failureCount, error) => shouldRetry | Boolean`
1867 - If `false`, failed queries will not retry by default.
1868 - If `true`, failed queries will retry infinitely.
1869 - If set to an `Int`, e.g. `3`, failed queries will retry until the failed query count meets that number.
1870- `retryDelay: Function(retryAttempt: Int) => Int`
1871 - This function receives a `retryAttempt` integer and returns the delay to apply before the next attempt in milliseconds.
1872 - A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff.
1873 - A function like `attempt => attempt * 1000` applies linear backoff.
1874- `staleTime: Int | Infinity`
1875 - The time in milliseconds that cache data remains fresh. After a successful cache update, that cache data will become stale after this duration.
1876 - If set to `Infinity`, query will never go stale
1877- `cacheTime: Int | Infinity`
1878 - The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration.
1879 - If set to `Infinity`, will disable garbage collection
1880- `refetchInterval: false | Integer`
1881 - Optional
1882 - If set to a number, all queries will continuously refetch at this frequency in milliseconds
1883- `refetchIntervalInBackground: Boolean`
1884 - Optional
1885 - If set to `true`, queries that are set to continuously refetch with a `refetchInterval` will continue to refetch while their tab/window is in the background
1886- `refetchOnWindowFocus: Boolean`
1887 - Optional
1888 - Set this to `false` to disable automatic refetching on window focus (useful, when `refetchAllOnWindowFocus` is set to `true`).
1889 - Set this to `true` to enable automatic refetching on window focus (useful, when `refetchAllOnWindowFocus` is set to `false`.
1890- `onSuccess: Function(data) => data`
1891 - Optional
1892 - This function will fire any time the query successfully fetches new data.
1893- `onError: Function(err) => void`
1894 - Optional
1895 - This function will fire if the query encounters an error and will be passed the error.
1896- `onSettled: Function(data, error) => data`
1897 - Optional
1898 - This function will fire any time the query is either successfully fetched or errors and be passed either the data or error
1899- `suspense: Boolean`
1900 - Optional
1901 - Set this to `true` to enable suspense mode.
1902 - When `true`, `useQuery` will suspend when `status === 'loading'`
1903 - When `true`, `useQuery` will throw runtime errors when `status === 'error'`
1904- `initialData: any | Function() => any`
1905 - Optional
1906 - If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet)
1907 - If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initialData
1908- `refetchOnMount: Boolean`
1909 - Optional
1910 - Defaults to `true`
1911 - If set to `false`, will disable additional instances of a query to trigger background refetches
1912- `queryFnParamsFilter: Function(args) => filteredArgs`
1913 - Optional
1914 - This function will filter the params that get passed to `queryFn`.
1915 - For example, you can filter out the first query key from the params by using `queryFnParamsFilter: args => args.slice(1)`.
1916
1917### Returns
1918
1919- `status: String`
1920 - Will be:
1921 - `loading` if the query is in an initial loading state. This means there is no cached data and the query is currently fetching, eg `isFetching === true`)
1922 - `error` if the query attempt resulted in an error. The corresponding `error` property has the error received from the attempted fetch
1923 - `success` if the query has received a response with no errors and is ready to display its data. The corresponding `data` property on the query is the data received from the successful fetch or if the query is in `manual` mode and has not been fetched yet `data` is the first `initialData` supplied to the query on initialization.
1924- `data: Any`
1925 - Defaults to `undefined`.
1926 - The last successfully resolved data for the query.
1927- `error: null | Error`
1928 - Defaults to `null`
1929 - The error object for the query, if an error was thrown.
1930- `isFetching: Boolean`
1931 - Defaults to `true` so long as `manual` is set to `false`
1932 - Will be `true` if the query is currently fetching, including background fetching.
1933- `failureCount: Integer`
1934 - The failure count for the query.
1935 - Incremented every time the query fails.
1936 - Reset to `0` when the query succeeds.
1937- `refetch: Function({ force, throwOnError }) => void`
1938 - A function to manually refetch the query if it is stale.
1939 - To bypass the stale check, you can pass the `force: true` option and refetch it regardless of it's freshness
1940 - If the query errors, the error will only be logged. If you want an error to be thrown, pass the `throwOnError: true` option
1941
1942## `usePaginatedQuery`
1943
1944```js
1945const {
1946 status,
1947 resolvedData,
1948 latestData,
1949 error,
1950 isFetching,
1951 failureCount,
1952 refetch,
1953} = usePaginatedQuery(queryKey, [, queryVariables], queryFn, {
1954 manual,
1955 retry,
1956 retryDelay,
1957 staleTime
1958 cacheTime,
1959 refetchInterval,
1960 refetchIntervalInBackground,
1961 refetchOnWindowFocus,
1962 onSuccess,
1963 onError,
1964 suspense,
1965 initialData,
1966 refetchOnMount
1967})
1968```
1969
1970### Options
1971
1972- `queryKey: String | [String, Variables: Object] | falsy | Function => queryKey`
1973 - **Required**
1974 - The query key to use for this query.
1975 - If a string is passed, it will be used as the query key.
1976 - If a `[String, Object]` tuple is passed, they will be serialized into a stable query key. See [Query Keys](#query-keys) for more information.
1977 - If a falsy value is passed, the query will be disabled and not run automatically.
1978 - If a function is passed, it should resolve to any other valid query key type. If the function throws, the query will be disabled and not run automatically.
1979 - The query will automatically update when this key changes (if the key is not falsy and if `manual` is not set to `true`).
1980 - `Variables: Object`
1981 - If a tuple with variables is passed, this object should be **serializable**.
1982 - Nested arrays and objects are supported.
1983 - The order of object keys is sorted to be stable before being serialized into the query key.
1984- `queryFn: Function(variables) => Promise(data/error)`
1985 - **Required**
1986 - The function that the query will use to request data.
1987 - Receives the following variables in the order that they are provided:
1988 - Query Key Variables
1989 - Optional Query Variables passed after the key and before the query function
1990 - Must return a promise that will either resolves data or throws an error.
1991- `manual: Boolean`
1992 - Set this to `true` to disable automatic refetching when the query mounts or changes query keys.
1993 - To refetch the query, use the `refetch` method returned from the `useQuery` instance.
1994- `retry: Boolean | Int | Function(failureCount, error) => shouldRetry | Boolean`
1995 - If `false`, failed queries will not retry by default.
1996 - If `true`, failed queries will retry infinitely.
1997 - If set to an `Int`, e.g. `3`, failed queries will retry until the failed query count meets that number.
1998- `retryDelay: Function(retryAttempt: Int) => Int`
1999 - This function receives a `retryAttempt` integer and returns the delay to apply before the next attempt in milliseconds.
2000 - A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff.
2001 - A function like `attempt => attempt * 1000` applies linear backoff.
2002- `staleTime: Int | Infinity`
2003 - The time in milliseconds that cache data remains fresh. After a successful cache update, that cache data will become stale after this duration.
2004 - If set to `Infinity`, query will never go stale
2005- `cacheTime: Int | Infinity`
2006 - The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration.
2007 - If set to `Infinity`, will disable garbage collection
2008- `refetchInterval: false | Integer`
2009 - Optional
2010 - If set to a number, all queries will continuously refetch at this frequency in milliseconds
2011- `refetchIntervalInBackground: Boolean`
2012 - Optional
2013 - If set to `true`, queries that are set to continuously refetch with a `refetchInterval` will continue to refetch while their tab/window is in the background
2014- `refetchOnWindowFocus: Boolean`
2015 - Optional
2016 - Set this to `false` to disable automatic refetching on window focus (useful, when `refetchAllOnWindowFocus` is set to `true`).
2017 - Set this to `true` to enable automatic refetching on window focus (useful, when `refetchAllOnWindowFocus` is set to `false`.
2018- `onSuccess: Function(data) => data`
2019 - Optional
2020 - This function will fire any time the query successfully fetches new data and will be passed the new data as a parameter
2021- `onError: Function(error) => void`
2022 - Optional
2023 - This function will fire if the query encounters an error and will be passed the error.
2024- `onSettled: Function(data, error) => data`
2025 - Optional
2026 - This function will fire any time the query is either successfully fetched or errors and be passed either the data or error
2027- `suspense: Boolean`
2028 - Optional
2029 - Set this to `true` to enable suspense mode.
2030 - When `true`, `useQuery` will suspend when `status === 'loading'`
2031 - When `true`, `useQuery` will throw runtime errors when `status === 'error'`
2032- `initialData: any`
2033 - Optional
2034 - If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet)
2035- `refetchOnMount: Boolean`
2036 - Optional
2037 - Defaults to `true`
2038 - If set to `false`, will disable additional instances of a query to trigger background refetches
2039
2040### Returns
2041
2042- `status: String`
2043 - Will be:
2044 - `loading` if the query is in an initial loading state. This means there is no cached data and the query is currently fetching, eg `isFetching === true`)
2045 - `error` if the query attempt resulted in an error. The corresponding `error` property has the error received from the attempted fetch
2046 - `success` if the query has received a response with no errors and is ready to display its data. The corresponding `data` property on the query is the data received from the successful fetch or if the query is in `manual` mode and has not been fetched yet `data` is the first `initialData` supplied to the query on initialization.
2047- `resolveData: Any`
2048 - Defaults to `undefined`.
2049 - The last successfully resolved data for the query.
2050 - When fetching based on a new query key, the value will resolve to the last known successful value, regardless of query key
2051- `latestData: Any`
2052 - Defaults to `undefined`.
2053 - The actual data object for this query and its specific query key
2054 - When fetching an uncached query, this value will be `undefined`
2055- `error: null | Error`
2056 - Defaults to `null`
2057 - The error object for the query, if an error was thrown.
2058- `isFetching: Boolean`
2059 - Defaults to `true` so long as `manual` is set to `false`
2060 - Will be `true` if the query is currently fetching, including background fetching.
2061- `failureCount: Integer`
2062 - The failure count for the query.
2063 - Incremented every time the query fails.
2064 - Reset to `0` when the query succeeds.
2065- `refetch: Function({ force, throwOnError }) => void`
2066 - A function to manually refetch the query if it is stale.
2067 - To bypass the stale check, you can pass the `force: true` option and refetch it regardless of it's freshness
2068 - If the query errors, the error will only be logged. If you want an error to be thrown, pass the `throwOnError: true` option
2069
2070## `useInfiniteQuery`
2071
2072```js
2073
2074const queryFn = (...queryKey, fetchMoreVariable) => Promise
2075
2076const {
2077 status,
2078 data,
2079 error,
2080 isFetching,
2081 failureCount,
2082 refetch,
2083} = useInfiniteQuery(queryKey, [, queryVariables], queryFn, {
2084 getFetchMore: (lastPage, allPages) => fetchMoreVariable
2085 manual,
2086 retry,
2087 retryDelay,
2088 staleTime
2089 cacheTime,
2090 refetchInterval,
2091 refetchIntervalInBackground,
2092 refetchOnWindowFocus,
2093 onSuccess,
2094 onError,
2095 suspense,
2096 initialData,
2097 refetchOnMount
2098})
2099```
2100
2101### Options
2102
2103- `queryKey: String | [String, Variables: Object] | falsy | Function => queryKey`
2104 - **Required**
2105 - The query key to use for this query.
2106 - If a string is passed, it will be used as the query key.
2107 - If a `[String, Object]` tuple is passed, they will be serialized into a stable query key. See [Query Keys](#query-keys) for more information.
2108 - If a falsy value is passed, the query will be disabled and not run automatically.
2109 - If a function is passed, it should resolve to any other valid query key type. If the function throws, the query will be disabled and not run automatically.
2110 - The query will automatically update when this key changes (if the key is not falsy and if `manual` is not set to `true`).
2111 - `Variables: Object`
2112 - If a tuple with variables is passed, this object should be **serializable**.
2113 - Nested arrays and objects are supported.
2114 - The order of object keys is sorted to be stable before being serialized into the query key.
2115- `queryFn: Function(variables) => Promise(data/error)`
2116 - **Required**
2117 - The function that the query will use to request data.
2118 - Receives the following variables in the order that they are provided:
2119 - Query Key Variables
2120 - Optional Query Variables passed after the key and before the query function
2121 - Optionally, the single variable returned from the `getFetchMore` function, used to fetch the next page
2122 - Must return a promise that will either resolves data or throws an error.
2123- `getFetchMore: Function(lastPage, allPages) => fetchMoreVariable | Boolean`
2124 - When new data is received for this query, this function receives both the last page of the infinite list of data and the full array of all pages.
2125 - It should return a **single variable** that will be passed as the last optional parameter to your query function
2126- `manual: Boolean`
2127 - Set this to `true` to disable automatic refetching when the query mounts or changes query keys.
2128 - To refetch the query, use the `refetch` method returned from the `useQuery` instance.
2129- `retry: Boolean | Int | Function(failureCount, error) => shouldRetry | Boolean`
2130 - If `false`, failed queries will not retry by default.
2131 - If `true`, failed queries will retry infinitely.
2132 - If set to an `Int`, e.g. `3`, failed queries will retry until the failed query count meets that number.
2133- `retryDelay: Function(retryAttempt: Int) => Int`
2134 - This function receives a `retryAttempt` integer and returns the delay to apply before the next attempt in milliseconds.
2135 - A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff.
2136 - A function like `attempt => attempt * 1000` applies linear backoff.
2137- `staleTime: Int | Infinity`
2138 - The time in milliseconds that cache data remains fresh. After a successful cache update, that cache data will become stale after this duration.
2139 - If set to `Infinity`, query will never go stale
2140- `cacheTime: Int | Infinity`
2141 - The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration.
2142 - If set to `Infinity`, will disable garbage collection
2143- `refetchInterval: false | Integer`
2144 - Optional
2145 - If set to a number, all queries will continuously refetch at this frequency in milliseconds
2146- `refetchIntervalInBackground: Boolean`
2147 - Optional
2148 - If set to `true`, queries that are set to continuously refetch with a `refetchInterval` will continue to refetch while their tab/window is in the background
2149- `refetchOnWindowFocus: Boolean`
2150 - Optional
2151 - Set this to `false` to disable automatic refetching on window focus (useful, when `refetchAllOnWindowFocus` is set to `true`).
2152 - Set this to `true` to enable automatic refetching on window focus (useful, when `refetchAllOnWindowFocus` is set to `false`.
2153- `onSuccess: Function(data) => data`
2154 - Optional
2155 - This function will fire any time the query successfully fetches new data.
2156- `onError: Function(err) => void`
2157 - Optional
2158 - This function will fire if the query encounters an error and will be passed the error.
2159- `onSettled: Function(data, error) => data`
2160 - Optional
2161 - This function will fire any time the query is either successfully fetched or errors and be passed either the data or error
2162- `suspense: Boolean`
2163 - Optional
2164 - Set this to `true` to enable suspense mode.
2165 - When `true`, `useQuery` will suspend when `status === 'loading'`
2166 - When `true`, `useQuery` will throw runtime errors when `status === 'error'`
2167- `initialData: any`
2168 - Optional
2169 - If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet)
2170- `refetchOnMount: Boolean`
2171 - Optional
2172 - Defaults to `true`
2173 - If set to `false`, will disable additional instances of a query to trigger background refetches
2174
2175### Returns
2176
2177- `status: String`
2178 - Will be:
2179 - `loading` if the query is in an initial loading state. This means there is no cached data and the query is currently fetching, eg `isFetching === true`)
2180 - `error` if the query attempt resulted in an error. The corresponding `error` property has the error received from the attempted fetch
2181 - `success` if the query has received a response with no errors and is ready to display its data. The corresponding `data` property on the query is the data received from the successful fetch or if the query is in `manual` mode and has not been fetched yet `data` is the first `initialData` supplied to the query on initialization.
2182- `data: Any`
2183 - Defaults to `[]`.
2184 - This array contains each "page" of data that has been requested
2185- `error: null | Error`
2186 - Defaults to `null`
2187 - The error object for the query, if an error was thrown.
2188- `isFetching: Boolean`
2189 - Defaults to `true` so long as `manual` is set to `false`
2190 - Will be `true` if the query is currently fetching, including background fetching.
2191- `isFetchingMore: Boolean`
2192 - If using `paginated` mode, this will be `true` when fetching more results using the `fetchMore` function.
2193- `failureCount: Integer`
2194 - The failure count for the query.
2195 - Incremented every time the query fails.
2196 - Reset to `0` when the query succeeds.
2197- `refetch: Function({ force, throwOnError }) => void`
2198 - A function to manually refetch the query if it is stale.
2199 - To bypass the stale check, you can pass the `force: true` option and refetch it regardless of it's freshness
2200 - If the query errors, the error will only be logged. If you want an error to be thrown, pass the `throwOnError: true` option
2201- `fetchMore: Function(fetchMoreVariableOverride) => Promise`
2202 - This function allows you to fetch the next "page" of results.
2203 - `fetchMoreVariableOverride` allows you to optionally override the fetch more variable returned from your `getCanFetchMore` option to your query function to retrieve the next page of results.
2204- `canFetchMore: Boolean`
2205 - If using `paginated` mode, this will be `true` if there is more data to be fetched (known via the required `getFetchMore` option function).
2206
2207## `useMutation`
2208
2209```js
2210const [mutate, { status, data, error, reset }] = useMutation(mutationFn, {
2211 onMutate
2212 onSuccess,
2213 onError,
2214 onSettled,
2215 throwOnError,
2216 useErrorBoundary,
2217 { ...selectedUseQueryOptions },
2218})
2219
2220const promise = mutate(variables, {
2221 onSuccess,
2222 onSettled,
2223 onError,
2224 throwOnError,
2225})
2226```
2227
2228### Options
2229
2230- `mutationFn: Function(variables) => Promise`
2231 - **Required**
2232 - A function that performs an asynchronous task and returns a promise.
2233 - `variables` is an object that `mutate` will pass to your `mutationFn`
2234- `onMutate: Function(variables) => Promise | snapshotValue`
2235 - Optional
2236 - This function will fire before the mutation function is fired and is passed the same variables the mutation function would receive
2237 - Useful to perform optimistic updates to a resource in hopes that the mutation succeeds
2238 - The value returned from this function will be passed to both the `onError` and `onSettled` functions and can be useful for rolling back optimistic updates in the event of a mutation failure.
2239- `onSuccess: Function(data, variables) => Promise | undefined`
2240 - Optional
2241 - This function will fire when the mutation is successful and will be passed the mutation's result.
2242 - Fires after the `mutate`-level `onSuccess` handler (if it is defined)
2243 - If a promise is returned, it will be awaited and resolved before proceeding
2244- `onError: Function(err, variables, onMutateValue) => Promise | undefined`
2245 - Optional
2246 - This function will fire if the mutation encounters an error and will be passed the error.
2247 - Fires after the `mutate`-level `onError` handerl (if it is defined)
2248 - If a promise is returned, it will be awaited and resolved before proceeding
2249- `onSettled: Function(data, error, variables, onMutateValue) => Promise | undefined`
2250 - Optional
2251 - This function will fire when the mutation is either successfully fetched or encounters an error and be passed either the data or error
2252 - Fires after the `mutate`-level `onSettled` handerl (if it is defined)
2253 - If a promise is returned, it will be awaited and resolved before proceeding
2254- `throwOnError`
2255 - Defaults to `false`
2256 - Set this to `true` if failed mutations should re-throw errors from the mutation function to the `mutate` function.
2257- `useErrorBoundary`
2258 - Defaults to the global query config's `useErrorBoundary` value, which is `false`
2259 - Set this to true if you want mutation errors to be thrown in the render phase and propagate to the nearest error boundary
2260- `selectedUseQueryOptions`
2261 - _Selected_ options of `useQuery` are also applicable here. E.g. `retry` and `retryDelay` can be used as described in the [`useQuery` section](#usequery). _Documentation of these options will be improved in the future._
2262
2263### Returns
2264
2265- `mutate: Function(variables, { onSuccess, onSettled, onError, throwOnError }) => Promise`
2266 - The mutation function you can call with variables to trigger the mutation and optionally override the original mutation options.
2267 - `variables: any`
2268 - Optional
2269 - The variables object to pass to the `mutationFn`.
2270 - Remaining options extend the same options described above in the `useMutation` hook.
2271 - Lifecycle callbacks defined here will fire **before** those of the same type defined in the `useMutation`-level options.
2272- `status: String`
2273 - Will be:
2274 - `idle` initial status prior to the mutation function executing.
2275 - `loading` if the mutation is currently executing.
2276 - `error` if the last mutation attempt resulted in an error.
2277 - `success` if the last mutation attempt was successful.
2278- `data: undefined | Any`
2279 - Defaults to `undefined`
2280 - The last successfully resolved data for the query.
2281- `error: null | Error`
2282 - The error object for the query, if an error was encountered.
2283- `promise: Promise`
2284 - The promise that is returned by the `mutationFn`.
2285
2286## `queryCache`
2287
2288The `queryCache` instance is the backbone of React Query that manages all of the state, caching, lifecycle and magic of every query. It supports relatively unrestricted, but safe, access to manipulate query's as you need. Its available properties and methods are:
2289
2290- [`prefetchQuery`](#querycacheprefetchquery)
2291- [`getQueryData`](#querycachegetquerydata)
2292- [`setQueryData`](#querycachesetquerydata)
2293- [`refetchQueries`](#querycacherefetchqueries)
2294- [`removeQueries`](#querycacheremovequeries)
2295- [`getQueries`](#querycachegetqueries)
2296- [`getQuery`](#querycachegetquery)
2297- [`subscribe`](#querycachesubscribe)
2298- [`isFetching`](#querycacheisfetching)
2299- [`clear`](#querycacheclear)
2300
2301## `queryCache.prefetchQuery`
2302
2303`prefetchQuery` is an asynchronous function that can be used to fetch and cache a query response before it is needed or fetched with `useQuery`.
2304
2305- If the query already exists and is fresh (not stale), the call will resolve immediately and no action will be taken.
2306 - If you want to force the query to prefetch again, you can pass the `force: true` option in the query config
2307- If the query does not exist, it will be created and immediately be marked as stale. **If this created query is not utilized by a query hook in the `cacheTime` (defaults to 5 minutes), the query will be garbage collected**.
2308
2309> The difference between using `prefetchQuery` and `setQueryData` is that `prefetchQuery` is async and will ensure that duplicate requests for this query are not created with `useQuery` instances for the same query are rendered while the data is fetching.
2310
2311```js
2312import { queryCache } from 'react-query'
2313
2314const data = await queryCache.prefetchQuery(queryKey, queryFn)
2315```
2316
2317For convenience in syntax, you can also pass optional query variables to `prefetchQuery` just like you can `useQuery`:
2318
2319```js
2320import { queryCache } from 'react-query'
2321
2322const data = await queryCache.prefetchQuery(
2323 queryKey,
2324 queryVariables,
2325 queryFn,
2326 config
2327)
2328```
2329
2330### Options
2331
2332The options for `prefetchQuery` are exactly the same as those of [`useQuery`](#usequery) with the exception of:
2333
2334- `config.throwOnError: Boolean`
2335 - Set this `true` if you want `prefetchQuery` to throw an error when it encounters errors.
2336
2337### Returns
2338
2339- `promise: Promise`
2340 - A promise is returned that will either immediately resolve with the query's cached response data, or resolve to the data returned by the fetch function. It **will not** throw an error if the fetch fails. This can be configured by setting the `throwOnError` option to `true`.
2341
2342## `queryCache.getQueryData`
2343
2344`getQueryData` is a synchronous function that can be used to get an existing query's cached data. If the query does not exist, `undefined` will be returned.
2345
2346```js
2347import { queryCache } from 'react-query'
2348
2349const data = queryCache.getQueryData(queryKey)
2350```
2351
2352### Options
2353
2354- `queryKey: QueryKey`
2355 - See [Query Keys](#query-keys) for more information on how to construct and use a query key
2356
2357### Returns
2358
2359- `data: any | undefined`
2360 - The data for the cached query, or `undefined` if the query does not exist.
2361
2362## `queryCache.setQueryData`
2363
2364`setQueryData` is a synchronous function that can be used to immediately update a query's cached data. If the query does not exist, it will be created and immediately be marked as stale. **If the query is not utilized by a query hook in the default `cacheTime` of 5 minutes, the query will be garbage collected**.
2365
2366> The difference between using `setQueryData` and `prefetchQuery` is that `setQueryData` is sync and assumes that you already synchronously have the data available. If you need to fetch the data asynchronously, it's suggested that you either refetch the query key or use `prefetchQuery` to handle the asynchronous fetch.
2367
2368```js
2369import { queryCache } from 'react-query'
2370
2371queryCache.setQueryData(queryKey, updater)
2372```
2373
2374### Options
2375
2376- `queryKey: QueryKey`
2377 - See [Query Keys](#query-keys) for more information on how to construct and use a query key
2378- `updater: Any | Function(oldData) => newData`
2379 - If non-function is passed, the data will be updated to this value
2380 - If a function is passed, it will receive the old data value and be expected to return a new one.
2381
2382### Using an updater value
2383
2384```js
2385setQueryData(queryKey, newData)
2386```
2387
2388### Using an updater function
2389
2390For convenience in syntax, you can also pass an updater function which receives the current data value and returns the new one:
2391
2392```js
2393setQueryData(queryKey, oldData => newData)
2394```
2395
2396## `queryCache.refetchQueries`
2397
2398The `refetchQueries` method can be used to refetch single or multiple queries in the cache based on their query keys or any other functionally accessible property/state of the query. By default, queries that are fresh (not stale) will not be refetched, but you can override this by passing the `force: true` option.
2399
2400```js
2401import { queryCache } from 'react-query'
2402
2403const queries = queryCache.refetchQueries(inclusiveQueryKeyOrPredicateFn, {
2404 exact,
2405 throwOnError,
2406 force,
2407})
2408```
2409
2410### Options
2411
2412- `queryKeyOrPredicateFn` can either be a [Query Key](#query-keys) or a `function`
2413 - `queryKey: QueryKey`
2414 - If a query key is passed, queries will be filtered to those where this query key is included in the existing query's query key. This means that if you passed a query key of `'todos'`, it would match queries with the `todos`, `['todos']`, and `['todos', 5]`. See [Query Keys](#query-keys) for more information.
2415 - `Function(query) => Boolean`
2416 - This predicate function will be called for every single query in the cache and be expected to return truthy for queries that are `found`.
2417 - The `exact` option has no effect with using a function
2418- `exact: Boolean`
2419 - If you don't want to search queries inclusively by query key, you can pass the `exact: true` option to return only the query with the exact query key you have passed. Don't remember to destructure it out of the array!
2420- `throwOnError: Boolean`
2421 - When set to `true`, this function will throw if any of the query refetch tasks fail.
2422- `force: Boolean`
2423 - When set to `true`, queries that match the refetch predicate will be refetched regardless if they are stale.
2424
2425### Returns
2426
2427This function returns a promise that will resolve when all of the queries are done being refetched. By default, it **will not** throw an error if any of those queries refetches fail, but this can be configured by setting the `throwOnError` option to `true`
2428
2429## `queryCache.removeQueries`
2430
2431The `removeQueries` method can be used to remove queries from the cache based on their query keys or any other functionally accessible property/state of the query.
2432
2433```js
2434import { queryCache } from 'react-query'
2435
2436const queries = queryCache.removeQueries(queryKeyOrPredicateFn, {
2437 exact,
2438})
2439```
2440
2441### Options
2442
2443- `queryKeyOrPredicateFn` can either be a [Query Key](#query-keys) or a `function`
2444 - `queryKey`
2445 - If a query key is passed, queries will be filtered to those where this query key is included in the existing query's query key. This means that if you passed a query key of `'todos'`, it would match queries with the `todos`, `['todos']`, and `['todos', 5]`. See [Query Keys](#query-keys) for more information.
2446 - `Function(query) => Boolean`
2447 - This predicate function will be called for every single query in the cache and be expected to return truthy for queries that are `found`.
2448 - The `exact` option has no effect with using a function
2449- `exact: Boolean`
2450 - If you don't want to search queries inclusively by query key, you can pass the `exact: true` option to return only the query with the exact query key you have passed. Don't remember to destructure it out of the array!
2451
2452### Returns
2453
2454This function does not return anything
2455
2456## `queryCache.getQuery`
2457
2458`getQuery` is a slightly more advanced synchronous function that can be used to get an existing query object from the cache. This object not only contains **all** the state for the query, but all of the instances, and underlying guts of the query as well. If the query does not exist, `undefined` will be returned.
2459
2460> Note: This is not typically needed for most applications, but can come in handy when needing more information about a query in rare scenarios (eg. Looking at the query.updatedAt timestamp to decide whether a query is fresh enough to be used as an initial value)
2461
2462```js
2463import { queryCache } from 'react-query'
2464
2465const query = queryCache.getQuery(queryKey)
2466```
2467
2468### Options
2469
2470- `queryKey: QueryKey`
2471 - See [Query Keys](#query-keys) for more information on how to construct and use a query key
2472
2473### Returns
2474
2475- `query: QueryObject`
2476 - The query object from the cache
2477
2478## `queryCache.getQueries`
2479
2480`getQueries` is even more advanced synchronous function that can be used to get existing query objects from the cache that partially match query key. If queries do not exist, empty array will be returned.
2481
2482> Note: This is not typically needed for most applications, but can come in handy when needing more information about a query in rare scenarios
2483
2484```js
2485import { queryCache } from 'react-query'
2486
2487const queries = queryCache.getQueries(queryKey)
2488```
2489
2490### Options
2491
2492- `queryKey: QueryKey`
2493 - See [Query Keys](#query-keys) for more information on how to construct and use a query key
2494
2495### Returns
2496
2497- `queries: QueryObject[]`
2498 - Query objects from the cache
2499
2500## `queryCache.isFetching`
2501
2502This `isFetching` property is an `integer` representing how many queries, if any, in the cache are currently fetching (including background-fetching, loading new pages, or loading more infinite query results)
2503
2504```js
2505import { queryCache } from 'react-query'
2506
2507if (queryCache.isFetching) {
2508 console.log('At least one query is fetching!')
2509}
2510```
2511
2512React Query also exports a handy [`useIsFetching`](#useisfetching) hook that will let you subscribe to this state in your components without creating a manual subscription to the query cache.
2513
2514## `queryCache.subscribe`
2515
2516The `subscribe` method can be used to subscribe to the query cache as a whole and be informed of safe/known updates to the cache like query states changing or queries being updated, added or removed
2517
2518```js
2519import { queryCache } from 'react-query'
2520
2521const callback = cache => {}
2522
2523const unsubscribe = queryCache.subscribe(callback)
2524```
2525
2526### Options
2527
2528- `callback: Function(queryCache) => void`
2529 - This function will be called with the query cache any time it is updated via its tracked update mechanisms (eg, `query.setState`, `queryCache.removeQueries`, etc). Out of scope mutations to the queryCache are not encouraged and will not fire subscription callbacks
2530
2531### Returns
2532
2533- `unsubscribe: Function => void`
2534 - This function will unsubscribe the callback from the query cache.
2535
2536## `queryCache.clear`
2537
2538The `clear` method can be used to clear the queryCache entirely and start fresh.
2539
2540```js
2541import { queryCache } from 'react-query'
2542
2543queryCache.clear()
2544```
2545
2546### Returns
2547
2548- `queries: Array<Query>`
2549 - This will be an array containing the queries that were found.
2550
2551## `useIsFetching`
2552
2553`useIsFetching` is an optional hook that returns the `number` of the queries that your application is loading or fetching in the background (useful for app-wide loading indicators).
2554
2555```js
2556import { useIsFetching } from 'react-query'
2557
2558const isFetching = useIsFetching()
2559```
2560
2561### Returns
2562
2563- `isFetching: Int`
2564 - Will be the `number` of the queries that your application is currently loading or fetching in the background.
2565
2566## `ReactQueryConfigProvider`
2567
2568`ReactQueryConfigProvider` is an optional provider component and can be used to define defaults for all instances of `useQuery` within it's sub-tree:
2569
2570```js
2571import { ReactQueryConfigProvider } from 'react-query'
2572
2573const queryConfig = {
2574 // Global
2575 suspense: false,
2576 useErrorBoundary: undefined, // Defaults to the value of `suspense` if not defined otherwise
2577 throwOnError: false,
2578 refetchAllOnWindowFocus: true,
2579 queryKeySerializerFn: queryKey => [queryHash, queryFnArgs],
2580 onMutate: () => {},
2581 onSuccess: () => {},
2582 onError: () => {},
2583 onSettled: () => {},
2584
2585 // useQuery
2586 retry: 3,
2587 retryDelay: attemptIndex => Math.min(1000 * 2 ** attemptIndex, 30000),
2588 staleTime: 0,
2589 cacheTime: 5 * 60 * 1000,
2590 refetchInterval: false,
2591 queryFnParamsFilter: args => filteredArgs,
2592 refetchOnMount: true,
2593 isDataEqual: (previous, next) => true, // or false
2594}
2595
2596function App() {
2597 return (
2598 <ReactQueryConfigProvider config={queryConfig}>
2599 ...
2600 </ReactQueryConfigProvider>
2601 )
2602}
2603```
2604
2605### Options
2606
2607- `config: Object`
2608 - Must be **stable** or **memoized**. Do not create an inline object!
2609 - For non-global properties please see their usage in both the [`useQuery` hook](#usequery) and the [`useMutation` hook](#usemutation).
2610
2611## `setConsole`
2612
2613`setConsole` is an optional utility function that allows you to replace the `console` interface used to log errors. By default, the `window.console` object is used. If no global `console` object is found in the environment, nothing will be logged.
2614
2615```js
2616import { setConsole } from 'react-query'
2617import { printLog, printWarn, printError } from 'custom-logger'
2618
2619setConsole({
2620 log: printLog,
2621 warn: printWarn,
2622 error: printError,
2623})
2624```
2625
2626### Options
2627
2628- `console: Object`
2629 - Must implement the `log`, `warn`, and `error` methods.
2630
2631# Contributors ✨
2632
2633Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
2634
2635<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
2636<!-- prettier-ignore-start -->
2637<!-- markdownlint-disable -->
2638<table>
2639 <tr>
2640 <td align="center"><a href="https://tannerlinsley.com"><img src="https://avatars0.githubusercontent.com/u/5580297?v=4" width="100px;" alt=""/><br /><sub><b>Tanner Linsley</b></sub></a><br /><a href="https://github.com/tannerlinsley/react-query/commits?author=tannerlinsley" title="Code">💻</a> <a href="#ideas-tannerlinsley" title="Ideas, Planning, & Feedback">🤔</a> <a href="#example-tannerlinsley" title="Examples">💡</a> <a href="#maintenance-tannerlinsley" title="Maintenance">🚧</a> <a href="https://github.com/tannerlinsley/react-query/pulls?q=is%3Apr+reviewed-by%3Atannerlinsley" title="Reviewed Pull Requests">👀</a></td>
2641 <td align="center"><a href="http://cherniavskii.com"><img src="https://avatars2.githubusercontent.com/u/13808724?v=4" width="100px;" alt=""/><br /><sub><b>Andrew Cherniavskii</b></sub></a><br /><a href="https://github.com/tannerlinsley/react-query/commits?author=cherniavskii" title="Code">💻</a> <a href="https://github.com/tannerlinsley/react-query/issues?q=author%3Acherniavskii" title="Bug reports">🐛</a></td>
2642 <td align="center"><a href="http://twitter.com/tibotiber"><img src="https://avatars3.githubusercontent.com/u/5635553?v=4" width="100px;" alt=""/><br /><sub><b>Thibaut Tiberghien</b></sub></a><br /><a href="https://github.com/tannerlinsley/react-query/commits?author=tibotiber" title="Documentation">📖</a></td>
2643 <td align="center"><a href="https://github.com/gargroh"><img src="https://avatars3.githubusercontent.com/u/42495927?v=4" width="100px;" alt=""/><br /><sub><b>Rohit Garg</b></sub></a><br /><a href="#tool-gargroh" title="Tools">🔧</a></td>
2644 </tr>
2645</table>
2646
2647<!-- markdownlint-enable -->
2648<!-- prettier-ignore-end -->
2649<!-- ALL-CONTRIBUTORS-LIST:END -->
2650
2651This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
2652
2653<!-- Force Toggle -->