Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs - extend detail for Queries & endpoints #1074

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
483 changes: 336 additions & 147 deletions docs/api/rtk-query/createApi.mdx

Large diffs are not rendered by default.

22 changes: 13 additions & 9 deletions docs/api/rtk-query/created-api/hooks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -267,11 +267,12 @@ type UseQueryResult<T> = {
startedTimeStamp?: number // Timestamp for when the query was initiated
fulfilledTimeStamp?: number // Timestamp for when the query was completed

isUninitialized: false // Query has not started yet.
isLoading: false // Query is currently loading for the first time. No data yet.
isFetching: false // Query is currently fetching, but might have data from an earlier request.
isSuccess: false // Query has data from a successful load.
isError: false // Query is currently in an "error" state.
// Derived request status booleans
isUninitialized: boolean // Query has not started yet.
isLoading: boolean // Query is currently loading for the first time. No data yet.
isFetching: boolean // Query is currently fetching, but might have data from an earlier request.
isSuccess: boolean // Query has data from a successful load.
isError: boolean // Query is currently in an "error" state.

refetch: () => void // A function to force refetch the query
}
Expand Down Expand Up @@ -316,15 +317,18 @@ type UseMutationTrigger<T> = (
}

type UseMutationResult<T> = {
// Base query state
originalArgs?: unknown // Arguments passed to the latest mutation call
data?: T // Returned result if present
endpointName?: string // The name of the given endpoint for the mutation
error?: unknown // Error result if present
endpointName?: string // The name of the given endpoint for the mutation
fulfilledTimestamp?: number // Timestamp for when the mutation was completed
isError: boolean // Mutation is currently in an "error" state

// Derived request status booleans
isUninitialized: boolean // Mutation has not been fired yet
isLoading: boolean // Mutation has been fired and is awaiting a response
isSuccess: boolean // Mutation has data from a successful call
isUninitialized: boolean // Mutation has not been fired yet
originalArgs?: unknown // Arguments passed to the latest mutation call
isError: boolean // Mutation is currently in an "error" state
startedTimeStamp?: number // Timestamp for when the latest mutation was initiated
}
```
Expand Down
6 changes: 3 additions & 3 deletions docs/usage/rtk-query/cached-data.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ RTK Query provides a number of concepts and tools to manipulate the cache behavi

### Tags

_see also: [tagTypes](../../api/rtk-query/createApi#tagtypes)_
_see also: [tagTypes API reference](../../api/rtk-query/createApi.mdx#tagtypes)_

For RTK Query, _tags_ are just a name that you can give to a specific collection of data to control caching and invalidation behavior for refetching purposes. It can be considered as a 'label' attached to cached data that is read after a `mutation`, to decide whether the data should be affected by the mutation.

Expand All @@ -25,15 +25,15 @@ An individual `tag` has a `type`, represented as a `string` name, and an optiona

### Providing tags

_see also: [Anatomy of an endpoint](../../api/rtk-query/createApi#anatomy-of-an-endpoint)_
_see also: [providesTags API reference](../../api/rtk-query/createApi.mdx#providestags)_

A _query_ can have it's cached data _provide_ tags. Doing so determines which 'tag' is attached to the cached data returned by the query.

The `providesTags` argument can either be an array of `string` (such as `['Post']`), `{type: string, id?: string|number}` (such as `[{type: 'Post', id: 1}]`), or a callback that returns such an array. That function will be passed the result as the first argument, the response error as the second argument, and the argument originally passed into the `query` method as the third argument. Note that either the result or error arguments may be undefined based on whether the query was successful or not.

### Invalidating tags

_see also: [Anatomy of an endpoint](../../api/rtk-query/createApi#anatomy-of-an-endpoint)_
_see also: [invalidatesTags API reference](../../api/rtk-query/createApi.mdx#invalidatesTags)_

A _mutation_ can _invalidate_ specific cached data based on the tags. Doing so determines which cached data will be either refetched or removed from the cache.

Expand Down
4 changes: 4 additions & 0 deletions docs/usage/rtk-query/conditional-fetching.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ If you want to prevent a query from automatically running, you can use the `skip

[remarks](docblock://query/react/buildHooks.ts?token=UseQuerySubscriptionOptions.skip)

:::tip
Typescript users may wish to use [`skipToken`](../../api/rtk-query/created-api/hooks.mdx#skiptoken) as an alternative to the `skip` option in order to skip running a query, while still keeping types for the endpoint accurate.
:::

### Example

<iframe
Expand Down
2 changes: 1 addition & 1 deletion docs/usage/rtk-query/customizing-queries.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ export const { useGetPostsQuery, useGetPostQuery } = api

### Excluding baseQuery with queryFn

Individual endpoints on [`createApi`](../../api/rtk-query/createApi) accept a [`queryFn`](../../api/rtk-query/createApi#anatomy-of-an-endpoint) property which allows a given endpoint to ignore `baseQuery` for that endpoint by providing an inline function determining how that query resolves.
Individual endpoints on [`createApi`](../../api/rtk-query/createApi) accept a [`queryFn`](../../api/rtk-query/createApi#queryfn) property which allows a given endpoint to ignore `baseQuery` for that endpoint by providing an inline function determining how that query resolves.

This can be useful for scenarios where you want to have particularly different behaviour for a single endpoint, or where the query itself is not relevant. Such situations may include:

Expand Down
74 changes: 32 additions & 42 deletions docs/usage/rtk-query/mutations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Unlike `useQuery`, `useMutation` returns a tuple. The first item in the tuple is

Unlike the `useQuery` hook, the `useMutation` hook doesn't execute automatically. To run a mutation you have to call the trigger function returned as the first tuple value from the hook.

See [`useMutation`](../../api/rtk-query/created-api/hooks.mdx#usemutation) for the hook signature and additional details.

```ts title="Example of all mutation endpoint options"
// file: types.ts noEmit
export interface Post {
Expand Down Expand Up @@ -68,47 +70,32 @@ const api = createApi({
Notice the `onQueryStarted` method? Be sure to check out how it can be used for [optimistic updates](./optimistic-updates)
:::

### Type interfaces

```ts title="Mutation endpoint definition" no-transpile
export type MutationDefinition<
QueryArg,
BaseQuery extends BaseQueryFn,
TagTypes extends string,
ResultType,
ReducerPath extends string = string,
Context = Record<string, any>
> = BaseEndpointDefinition<QueryArg, BaseQuery, ResultType> & {
type: DefinitionType.mutation
invalidatesTags?: ResultDescription<TagTypes, ResultType, QueryArg>
providesTags?: never
onQueryStarted?(
arg: QueryArg,
{
dispatch,
getState,
queryFulfilled,
requestId,
extra,
getCacheEntry,
}: MutationLifecycleApi
): Promise<void>
onCacheEntryAdded?(
arg: QueryArg,
{
dispatch,
getState,
extra,
requestId,
cacheEntryRemoved,
cacheDataLoaded,
getCacheEntry,
}: MutationCacheLifecycleApi
): Promise<void>
}
```
### Performing Mutations with React Hooks

#### Frequently Used Mutation Hook Return Values

The `useMutation` hook returns a tuple containing a `mutation trigger` function, as well as an object containing properties about the `mutation result`.

The `mutation trigger` is a function that when called, will fire off the mutation request for that endpoint. Calling the `mutation trigger` returns a promise with an `unwrap` property, which can be called to unwrap the mutation call and provide the raw response/error. This can be useful if you wish to determine whether the mutation succeeds/fails inline at the call-site.

The `mutation result` is an object containing properties such as the latest `data` for the mutation request, as well as status booleans for the current request lifecycle state.

Below are some of the most frequently used properties on the `mutation result` object. Refer to [`useMutation`](../../api/rtk-query/created-api/hooks.mdx#usemutation) for an extensive list of all returned properties.

- `data` - The returned result if present.
- `error` - The error result if present.
- `isUninitialized` - When true, indicates that the mutation has not been fired yet.
- `isLoading` - When true, indicates that the mutation has been fired and is awaiting a response.
- `isSuccess` - When true, indicates that the last mutation fired has data from a successful request.
- `isError` - When true, indicates that the last mutation fired resulted in an error state.

:::note

With RTK Query, a mutation does contain a semantic distinction between 'loading' and 'fetching' in the way that a [query does](./queries.mdx#frequently-used-query-hook-return-values). For a mutation, subsequent calls are not assumed to be necessarily related, so a mutation is either 'loading' or 'not loading', with no concept of 're-fetching'.

:::

### Basic Mutation
#### Example

This is a modified version of the complete example you can see at the bottom of the page to highlight the `updatePost` mutation. In this scenario, a post is fetched with `useQuery`, and then a `EditablePostName` component is rendered that allows us to edit the name of the post.

Expand All @@ -118,11 +105,12 @@ export const PostDetail = () => {

const { data: post } = useGetPostQuery(id)

// highlight-start
const [
// highlight-next-line
updatePost, // This is the mutation trigger
{ isLoading: isUpdating }, // You can use the `isLoading` flag, or do custom logic with `status`
{ isLoading: isUpdating }, // This is the destructured mutation result
] = useUpdatePostMutation()
// highlight-end

return (
<Box p={4}>
Expand All @@ -140,7 +128,9 @@ export const PostDetail = () => {
// highlight-end
)
}}
// highlight-start
isLoading={isUpdating}
// highlight-end
/>
</Box>
)
Expand Down
70 changes: 33 additions & 37 deletions docs/usage/rtk-query/queries.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ By default, RTK Query ships with [`fetchBaseQuery`](../../api/rtk-query/fetchBas

> Depending on your environment, you may need to polyfill `fetch` with `node-fetch` or `cross-fetch` if you choose to use `fetchBaseQuery` or `fetch` on its own.

See [`useQuery`](../../api/rtk-query/created-api/hooks.mdx#usequery) for the hook signature and additional details.

```ts title="Example of all query endpoint options"
// file: types.ts noEmit
export interface Post {
Expand Down Expand Up @@ -71,7 +73,7 @@ const api = createApi({
})
```

### Performing queries with React Hooks
### Performing Queries with React Hooks

If you're using React Hooks, RTK Query does a few additional things for you. The primary benefit is that you get a render-optimized hook that allows you to have 'background fetching' as well as [derived booleans](#query-hook-return-types) for convenience.

Expand All @@ -81,48 +83,42 @@ Hooks are automatically generated based on the name of the `endpoint` in the ser

There are 5 query-related hooks:

1. [`useQuery`](../../api/rtk-query/created-api/hooks/#usequery)
- Composes `useQuerySubscription` and `useQueryState` and is the primary hook
2. [`useQuerySubscription`](../../api/rtk-query/created-api/hooks/#usequerysubscription)
- Returns a `refetch` function and accepts all hook options
3. [`useQueryState`](../../api/rtk-query/created-api/hooks/#usequerystate)
- Returns the query state and accepts `skip` and `selectFromResult`
4. [`useLazyQuery`](../../api/rtk-query/created-api/hooks/#uselazyquery)
- Returns a tuple with a `fetch` function, the query result, and last promise info
5. [`useLazyQuerySubscription`](../../api/rtk-query/created-api/hooks/#uselazyquerysubscription)
- Returns a tuple with a `fetch` function, and last promise info
1. [`useQuery`](../../api/rtk-query/created-api/hooks.mdx#usequery)
- Composes `useQuerySubscription` and `useQueryState` and is the primary hook. Automatically triggers fetches of data from an endpoint, 'subscribes' the component to the cached data, and reads the request status and cached data from the Redux store.
2. [`useQuerySubscription`](../../api/rtk-query/created-api/hooks.mdx#usequerysubscription)
- Returns a `refetch` function and accepts all hook options. Automatically triggers fetches of data from an endpoint, and 'subscribes' the component to the cached data.
3. [`useQueryState`](../../api/rtk-query/created-api/hooks.mdx#usequerystate)
- Returns the query state and accepts `skip` and `selectFromResult`. Reads the request status and cached data from the Redux store.
4. [`useLazyQuery`](../../api/rtk-query/created-api/hooks.mdx#uselazyquery)
- Returns a tuple with a `fetch` function, the query result, and last promise info. Similar to `useQuery`, but with manual control over when the data fetching occurs.
5. [`useLazyQuerySubscription`](../../api/rtk-query/created-api/hooks.mdx#uselazyquerysubscription)
- Returns a tuple with a `fetch` function, and last promise info. Similar to `useQuerySubscription`, but with manual control over when the data fetching occurs.

#### Query Hook Options

- [skip](./conditional-fetching) - Defaults to `false`
- [pollingInterval](./polling) - Defaults to `0` _(off)_
- [selectFromResult](#selecting-data-from-a-query-result) - Optional, allows you to return a subset of a query
- [refetchOnMountOrArgChange](../../api/rtk-query/createApi#refetchonmountorargchange) - Defaults to `false`
- [refetchOnFocus](../../api/rtk-query/createApi#refetchonfocus) - Defaults to `false`
- [refetchOnReconnect](../../api/rtk-query/createApi#refetchonreconnect) - Defaults to `false`
- [skip](./conditional-fetching) - Allows a query to 'skip' running for that render. Defaults to `false`
- [pollingInterval](./polling) - Allows a query to automatically refetch on a provided interval, specified in milliseconds. Defaults to `0` _(off)_
- [selectFromResult](#selecting-data-from-a-query-result) - Allows altering the returned value of the hook to obtain a subset of the result, render-optimized for the returned subset.
- [refetchOnMountOrArgChange](../../api/rtk-query/createApi#refetchonmountorargchange) - Allows forcing the query to always refetch on mount (when `true` is provided). Allows forcing the query to refetch if enough time (in seconds) has passed since the last query for the same cache (when a `number` is provided). Defaults to `false`
- [refetchOnFocus](../../api/rtk-query/createApi#refetchonfocus) - Allows forcing the query to refetch when the browser window regains focus. Defaults to `false`
- [refetchOnReconnect](../../api/rtk-query/createApi#refetchonreconnect) - Allows forcing the query to refetch when regaining a network connection. Defaults to `false`

> All `refetch`-related options will override the defaults you may have set in [createApi](../../api/rtk-query/createApi)

#### Query Hook Return Types

```ts title="All returned elements" no-transpile
// Base query state
originalArgs?: unknown; // Arguments passed to the query
data?: unknown; // Returned result if present
error?: unknown; // Error result if present
requestId?: string; // A string generated by RTK Query
endpointName?: string; // The name of the given endpoint for the query
startedTimeStamp?: number; // Timestamp for when the query was initiated
fulfilledTimeStamp?: number; // Timestamp for when the query was completed

isUninitialized: false; // Query has not started yet.
isLoading: false; // Query is currently loading for the first time. No data yet.
isFetching: false; // Query is currently fetching, but might have data from an earlier request.
isSuccess: false; // Query has data from a successful load.
isError: false; // Query is currently in "error" state.

refetch: () => void; // A function to force refetch the query
```
#### Frequently Used Query Hook Return Values

The query hook returns an object containing properties such as the latest `data` for the query request, as well as status booleans for the current request lifecycle state. Below are some of the most frequently used properties. Refer to [`useQuery`](../../api/rtk-query/created-api/hooks.mdx#usequery) for an extensive list of all returned properties.

- `data` - The returned result if present.
- `error` - The error result if present.
- `isUninitialized` - When true, indicates that the query has not started yet.
- `isLoading` - When true, indicates that the query is currently loading for the first time, and has no data yet. This will be `true` for the first request fired off, but _not_ for subsequent requests.
- `isFetching` - When true, indicates that the query is currently fetching, but might have data from an earlier request. This will be `true` for both the first request fired off, as well as subsequent requests.
- `isSuccess` - When true, indicates that the query has data from a successful request.
- `isError` - When true, indicates that the query is in an `error` state.
- `refetch` - A function to force refetch the query

#### Example

Here is an example of a `PostDetail` component:

Expand Down
2 changes: 1 addition & 1 deletion docs/usage/rtk-query/streaming-updates.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ RTK Query gives you the ability to receive **streaming updates** for persistent

Streaming updates can be used to enable the API to receive real-time updates to the back-end data, such as new entries being created, or important properties being updated.

To enable streaming updates for a query, pass the asynchronous `onCacheEntryAdded` function to the query, including the logic for how to update the query when streamed data is received. See [anatomy of an endpoint](../../api/rtk-query/createApi#anatomy-of-an-endpoint) for more details.
To enable streaming updates for a query, pass the asynchronous `onCacheEntryAdded` function to the query, including the logic for how to update the query when streamed data is received. See [`onCacheEntryAdded` API reference](../../api/rtk-query/createApi#onCacheEntryAdded) for more details.

## When to use streaming updates

Expand Down
2 changes: 1 addition & 1 deletion src/query/core/buildMiddleware/cacheLifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ declare module '../../endpointDefinitions' {
>
/**
* Updates the current cache entry value.
* For documentation see `api.util.updateQueryData.
* For documentation see `api.util.updateQueryData`.
*/
updateCachedData(updateRecipe: Recipe<ResultType>): PatchCollection
}
Expand Down
23 changes: 23 additions & 0 deletions src/query/createApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,29 @@ export interface CreateApiOptions<
): Definitions
/**
* Defaults to `60` _(this value is in seconds)_. This is how long RTK Query will keep your data cached for **after** the last component unsubscribes. For example, if you query an endpoint, then unmount the component, then mount another component that makes the same request within the given time frame, the most recent value will be served from the cache.
*
* ```ts
* // codeblock-meta title="keepUnusedDataFor example"
*
* import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
* interface Post {
* id: number
* name: string
* }
* type PostsResponse = Post[]
*
* const api = createApi({
* baseQuery: fetchBaseQuery({ baseUrl: '/' }),
* endpoints: (build) => ({
* getPosts: build.query<PostsResponse, void>({
* query: () => 'posts',
* // highlight-start
* keepUnusedDataFor: 5
* // highlight-end
* })
* })
* })
* ```
*/
keepUnusedDataFor?: number
/**
Expand Down
Loading