Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/feature/v1.6-integration' into f…
Browse files Browse the repository at this point in the history
…eature/lifecycles
  • Loading branch information
phryneas committed May 13, 2021
2 parents 1f0b4e9 + a42a9f2 commit 2b7c65b
Show file tree
Hide file tree
Showing 39 changed files with 2,449 additions and 548 deletions.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,25 @@ hide_title: true

# `createApi`

`createApi` is the core of RTK Query's functionality. It allows you to define a set of endpoints describe how to retrieve data from a series of endpoints, including configuration of how to fetch and transform that data. It generates [an "API slice" structure](./created-api/overview.md) that contains Redux logic (and optionally React hooks) that encapsulate the data fetching and caching process for you.
`createApi` is the core of RTK Query's functionality. It allows you to define a set of endpoints describe how to retrieve data from a series of endpoints, including configuration of how to fetch and transform that data. It generates [an "API slice" structure](./created-api/overview.mdx) that contains Redux logic (and optionally React hooks) that encapsulate the data fetching and caching process for you.

```ts title="Example: src/services/pokemon.ts"
// file: src/services/types.ts noEmit
export type Pokemon = {}

// file: src/services/pokemon.ts
// Need to use the React-specific entry point to allow generating React hooks
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/react'
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import type { Pokemon } from './types'

// highlight-start
// Define a service using a base URL and expected endpoints
export const pokemonApi = createApi({
reducerPath: 'pokemonApi',
baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
endpoints: (builder) => ({
getPokemonByName: builder.query({
query: (name: string) => `pokemon/${name}`,
getPokemonByName: builder.query<Pokemon, string>({
query: (name) => `pokemon/${name}`,
}),
}),
})
Expand Down Expand Up @@ -71,7 +76,7 @@ export const { useGetPokemonByNameQuery } = pokemonApi

Defaults to:

```ts no-compile
```ts no-transpile
export const defaultSerializeQueryArgs: SerializeQueryArgs<any> = ({
endpoint,
queryArgs,
Expand Down Expand Up @@ -108,15 +113,15 @@ export const defaultSerializeQueryArgs: SerializeQueryArgs<any> = ({

- `providesTags` _(optional)_

[summary](docblock://query/endpointDefinitions.ts?token=QueryExtraOptions.provides)
[summary](docblock://query/endpointDefinitions.ts?token=QueryExtraOptions.providesTags)

- `invalidatesTags` _(optional)_

[summary](docblock://query/endpointDefinitions.ts?token=MutationExtraOptions.invalidates)
[summary](docblock://query/endpointDefinitions.ts?token=MutationExtraOptions.invalidatesTags)

- `onQuery` _(optional)_ - Available to both [queries](../../usage/rtk-query/queries.md) and [mutations](../../usage/rtk-query/mutations.md)
- Can be used in `mutations` for [optimistic updates](../../usage/rtk-query/optimistic-updates.md).
- ```ts title="Mutation onQuery signature"
- `onQuery` _(optional)_ - Available to both [queries](../../usage/rtk-query/queries.mdx) and [mutations](../../usage/rtk-query/mutations.mdx)
- Can be used in `mutations` for [optimistic updates](../../usage/rtk-query/optimistic-updates.mdx).
- ```ts title="Mutation onQuery signature" no-transpile
async function onQuery(
arg: QueryArg,
{
Expand All @@ -129,7 +134,7 @@ export const defaultSerializeQueryArgs: SerializeQueryArgs<any> = ({
}: MutationLifecycleApi
): Promise<void>
```
- ```ts title="Query onQuery signature"
- ```ts title="Query onQuery signature" no-transpile
async function onQuery(
arg: QueryArg,
{
Expand All @@ -143,10 +148,10 @@ export const defaultSerializeQueryArgs: SerializeQueryArgs<any> = ({
}: QueryLifecycleApi
): Promise<void>
```
- `onCacheEntryAdded` _(optional)_ - Available to both [queries](../../usage/rtk-query/queries.md) and [mutations](../../usage/rtk-query/mutations.md)
- `onCacheEntryAdded` _(optional)_ - Available to both [queries](../../usage/rtk-query/queries.mdx) and [mutations](../../usage/rtk-query/mutations.mdx)

- Can be used for TODO
- ```ts title="Mutation onCacheEntryAdded signature"
- ```ts title="Mutation onCacheEntryAdded signature" no-transpile
async function onCacheEntryAdded(
arg: QueryArg,
{
Expand All @@ -160,7 +165,7 @@ export const defaultSerializeQueryArgs: SerializeQueryArgs<any> = ({
}: MutationCacheLifecycleApi
): Promise<void>
```
- ```ts title="Query onCacheEntryAdded signature"
- ```ts title="Query onCacheEntryAdded signature" no-transpile
async function onCacheEntryAdded(
arg: QueryArg,
{
Expand All @@ -181,12 +186,21 @@ export const defaultSerializeQueryArgs: SerializeQueryArgs<any> = ({
When defining a key like `getPosts` as shown below, it's important to know that this name will become exportable from `api` and be able to referenced under `api.endpoints.getPosts.useQuery()`, `api.endpoints.getPosts.initiate()` and `api.endpoints.getPosts.select()`. The same thing applies to `mutation`s but they reference `useMutation` instead of `useQuery`.
```ts
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
interface Post {
id: number
name: string
}
type PostsResponse = Post[]
const api = createApi({
baseQuery: fetchBaseQuery('/'),
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
tagTypes: ['Posts'],
endpoints: (build) => ({
getPosts: build.query<PostsResponse, void>({
query: () => 'posts',
provides: (result) => result ? result.map(({ id }) => ({ type: 'Posts', id })) : [],
provides: (result) =>
result ? result.map(({ id }) => ({ type: 'Posts', id })) : [],
}),
addPost: build.mutation<Post, Partial<Post>>({
query: (body) => ({
Expand All @@ -197,13 +211,13 @@ const api = createApi({
invalidates: ['Posts'],
}),
}),
});
})
// Auto-generated hooks
export { useGetPostsQuery, useAddPostMutation } = api;
export const { useGetPostsQuery, useAddPostMutation } = api
// Possible exports
export const { endpoints, reducerPath, reducer, middleware } = api;
export const { endpoints, reducerPath, reducer, middleware } = api
// reducerPath, reducer, middleware are only used in store configuration
// endpoints will have:
// endpoints.getPosts.initiate(), endpoints.getPosts.select(), endpoints.getPosts.useQuery()
Expand All @@ -225,17 +239,32 @@ function defaultTransformResponse(baseQueryReturnValue: unknown) {
To change it, provide a function that looks like:
```ts
```ts no-transpile
transformResponse: (response) => response.some.deeply.nested.property
```
```ts title="GraphQL transformation example"
// file: graphqlBaseQuery.ts noEmit
import { BaseQueryFn } from '@reduxjs/toolkit/query'
declare const graphqlBaseQuery: (args: { baseUrl: string }) => BaseQueryFn
declare const gql: (literals: TemplateStringsArray) => void
export { graphqlBaseQuery, gql }
// file: graphqlApi.ts
import { createApi } from '@reduxjs/toolkit/query'
import { graphqlBaseQuery, gql } from './graphqlBaseQuery'
interface Post {
id: number
title: string
}
export const api = createApi({
baseQuery: graphqlBaseQuery({
baseUrl: '/graphql',
}),
endpoints: (builder) => ({
getPosts: builder.query({
getPosts: builder.query<Post[], void>({
query: () => ({
body: gql`
query {
Expand All @@ -248,7 +277,8 @@ export const api = createApi({
}
`,
}),
transformResponse: (response) => response.posts.data,
transformResponse: (response: { posts: { data: Post[] } }) =>
response.posts.data,
}),
}),
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ hide_title: true

# API Slices: Cache Management Utilities

The API slice object includes cache management utilities that are used for implementing [optimistic updates](../../../usage/rtk-query/optimistic-updates.md). These are included in a `util` field inside the slice object.
The API slice object includes cache management utilities that are used for implementing [optimistic updates](../../../usage/rtk-query/optimistic-updates.mdx). These are included in a `util` field inside the slice object.

### `updateQueryResult`

#### Signature

```ts
```ts no-transpile
const updateQueryResult = (
endpointName: string,
args: any,
Expand Down Expand Up @@ -45,7 +45,7 @@ This is typically used as the first step in implementing optimistic updates. The

#### Signature

```ts
```ts no-transpile
const patchQueryResult = (
endpointName: string,
args: any
Expand All @@ -65,7 +65,7 @@ This is typically used as the second step in implementing optimistic updates. If

#### Signature

```ts
```ts no-transpile
type PrefetchOptions = { ifOlderThan?: false | number } | { force?: boolean };

const prefetch = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ hide_title: true

# API Slices: Code Splitting and Generation

Each API slice allows [additional endpoint definitions to be injected at runtime](../../../usage/rtk-query/code-splitting.md) after the initial API slice has been defined. This can be beneficial for apps that may have _many_ endpoints.
Each API slice allows [additional endpoint definitions to be injected at runtime](../../../usage/rtk-query/code-splitting.mdx) after the initial API slice has been defined. This can be beneficial for apps that may have _many_ endpoints.

The individual API slice endpoint definitions can also be split across multiple files. This is primarily useful for working with API slices that were [code-generated from an API schema file](../../../usage/rtk-query/code-generation.md), allowing you to add additional custom behavior and configuration to a set of automatically-generated endpoint definitions.
The individual API slice endpoint definitions can also be split across multiple files. This is primarily useful for working with API slices that were [code-generated from an API schema file](../../../usage/rtk-query/code-generation.mdx), allowing you to add additional custom behavior and configuration to a set of automatically-generated endpoint definitions.

Each API slice object has `injectEndpoints` and `enhanceEndpoints` functions to support these use cases.

## `injectEndpoints`

#### Signature

```ts
```ts no-transpile
const injectEndpoints = (endpointOptions: InjectedEndpointOptions) =>
EnhancedApiSlice

Expand All @@ -29,7 +29,7 @@ interface InjectedEndpointOptions {

#### Description

Accepts an options object containing the same `endpoints` builder callback you would pass to [`createApi.endpoints`](../createApi.md#endpoints). Any endpoint definitions defined using that builder will be merged into the existing endpoint definitions for this API slice using a shallow merge, so any new endpoint definitions will override existing endpoints with the same name.
Accepts an options object containing the same `endpoints` builder callback you would pass to [`createApi.endpoints`](../createApi.mdx#endpoints). Any endpoint definitions defined using that builder will be merged into the existing endpoint definitions for this API slice using a shallow merge, so any new endpoint definitions will override existing endpoints with the same name.

Returns an updated and enhanced version of the API slice object, containing the combined endpoint definitions.

Expand All @@ -41,7 +41,7 @@ This method is primarily useful for code splitting and hot reloading.

#### Signature

```ts
```ts no-transpile
const enhanceEndpoints = (endpointOptions: EnhanceEndpointsOptions) =>
EnhancedApiSlice

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The API slice object will have an `endpoints` field inside. This section maps th

Each endpoint structure contains the following fields:

```ts
```ts no-transpile
type EndpointLogic = {
initiate: InitiateRequestThunk
select: CreateCacheSelectorFactory
Expand All @@ -25,7 +25,7 @@ type EndpointLogic = {
#### Signature
```ts
```ts no-transpile
type InitiateRequestThunk = StartQueryActionCreator | StartMutationActionCreator;

type StartQueryActionCreator = (
Expand Down Expand Up @@ -85,14 +85,14 @@ A Redux thunk action creator that you can dispatch to trigger data fetch queries
React Hooks users will most likely never need to use these directly, as the hooks automatically dispatch these actions as needed.

:::note Usage of actions outside of React Hooks
When dispatching an action creator, you're responsible for storing a reference to the promise it returns in the event that you want to update that specific subscription. Also, you have to manually unsubscribe once your component unmounts. To get an idea of what that entails, see the [Svelte Example](../../../usage/rtk-query/examples.md#svelte) or the [React Class Components Example](../../../usage/rtk-query/examples.md#react-class-components)
When dispatching an action creator, you're responsible for storing a reference to the promise it returns in the event that you want to update that specific subscription. Also, you have to manually unsubscribe once your component unmounts. To get an idea of what that entails, see the [Svelte Example](../../../usage/rtk-query/examples.mdx#svelte) or the [React Class Components Example](../../../usage/rtk-query/examples.mdx#react-class-components)
:::

## `select`

#### Signature

```ts
```ts no-transpile
type CreateCacheSelectorFactory =
| QueryResultSelectorFactory
| MutationResultSelectorFactory
Expand Down Expand Up @@ -129,7 +129,7 @@ Each call to `.select(someCacheKey)` returns a _new_ selector function instance.
A set of [Redux Toolkit action matching utilities](https://redux-toolkit.js.org/api/matching-utilities) that match the `pending`, `fulfilled`, and `rejected` actions that will be dispatched by this thunk. These allow you to match on Redux actions for that endpoint, such as in `createSlice.extraReducers` or a custom middleware. Those are implemented as follows:
```ts
```ts no-transpile
matchPending: isAllOf(isPending(thunk), matchesEndpoint(endpoint)),
matchFulfilled: isAllOf(isFulfilled(thunk), matchesEndpoint(endpoint)),
matchRejected: isAllOf(isRejected(thunk), matchesEndpoint(endpoint)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ The core RTK Query `createApi` method is UI-agnostic, in the same way that the R

However, RTK Query also provides the ability to auto-generate React hooks for each of your endpoints. Since this specifically depends on React itself, RTK Query provides an alternate entry point that exposes a customized version of `createApi` that includes that functionality:

```js
```ts no-transpile
import { createApi } from '@reduxjs/toolkit/query/react'
```

Expand All @@ -23,7 +23,7 @@ The same hooks are also added to the `Api` object itself, and given auto-generat

For example, if you had endpoints for `getPosts` and `updatePost`, these options would be available:

```ts title="Generated React Hook names"
```ts title="Generated React Hook names" no-transpile
// Hooks attached to the endpoint definition
const { data } = api.endpoints.getPosts.useQuery()
const [updatePost, { data }] = api.endpoints.updatePost.useMutation()
Expand All @@ -47,7 +47,7 @@ The full list of hooks generated in the React-specific version of `createApi` is

For the example above, the full set of generated hooks for the api would be like so:

```ts title="Generated React Hooks"
```ts title="Generated React Hooks" no-transpile
/* Hooks attached to the `getPosts` query endpoint definition */
const { data } = api.endpoints.getPosts.useQuery(arg, options)
const post = api.endpoints.getPosts.useQueryState(arg, options)
Expand Down Expand Up @@ -195,7 +195,7 @@ The provided hooks have a degree of feature overlap in order to provide options

#### Signature

```ts
```ts no-transpile
type UseQuery = (arg: any, options?: UseQueryOptions) => UseQueryResult

type UseQueryOptions = {
Expand Down Expand Up @@ -241,7 +241,7 @@ type UseQueryResult<T> = {
#### Signature
```ts
```ts no-transpile
type UseMutation = (
options?: UseMutationStateOptions
) => [UseMutationTrigger, UseMutationResult | SelectedUseMutationResult]
Expand Down Expand Up @@ -280,7 +280,7 @@ The generated `UseMutation` hook will cause a component to re-render by default
Returning a completely empty object will mean that any individual mutation call will cause only one re-render at most, e.g.
```ts
```ts no-transpile
selectFromResult: () => ({})
```
Expand All @@ -302,7 +302,7 @@ selectFromResult: () => ({})
#### Signature
```ts
```ts no-transpile
type UseQueryState = (
arg: any,
options?: UseQueryStateOptions
Expand Down Expand Up @@ -351,7 +351,7 @@ type UseQueryStateResult<T> = {
#### Signature
```ts
```ts no-transpile
type UseQuerySubscription = (
arg: any,
options?: UseQuerySubscriptionOptions
Expand Down Expand Up @@ -386,7 +386,7 @@ type UseQuerySubscriptionResult = {
#### Signature
```ts
```ts no-transpile
type UseLazyQuery = (
options?: UseLazyQueryOptions
) => [UseLazyQueryTrigger, UseQueryStateResult, UseLazyQueryLastPromiseInfo]
Expand Down Expand Up @@ -443,7 +443,7 @@ type UseLazyQueryLastPromiseInfo = {
#### Signature
```ts
```ts no-transpile
type UseLazyQuerySubscription = (
options?: UseLazyQuerySubscriptionOptions
) => [UseLazyQuerySubscriptionTrigger, LastArg]
Expand Down Expand Up @@ -473,7 +473,7 @@ type UseLazyQuerySubscriptionTrigger = (arg: any) => void
#### Signature
```ts
```ts no-transpile
type UsePrefetch = (
endpointName: string,
options?: UsePrefetchOptions
Expand Down
Loading

0 comments on commit 2b7c65b

Please sign in to comment.