Skip to content

Commit

Permalink
Merge pull request reduxjs#1565 from reduxjs/v1.7.0-integration
Browse files Browse the repository at this point in the history
  • Loading branch information
markerikson authored Dec 10, 2021
2 parents cecda16 + aad6d32 commit db0d7dc
Show file tree
Hide file tree
Showing 68 changed files with 2,941 additions and 707 deletions.
6 changes: 6 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ module.exports = {
'error',
{ prefer: 'type-imports', disallowTypeAnnotations: false },
],
'react-hooks/exhaustive-deps': [
'warn',
{
additionalHooks: '(usePossiblyImmediateEffect)',
},
],
},
overrides: [
// {
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ jobs:
fail-fast: false
matrix:
node: ['14.x']
ts: ['3.9', '4.0', '4.1', '4.2', '4.3', 'next']
ts: ['3.9', '4.0', '4.1', '4.2', '4.3', '4.4', '4.5', 'next']
steps:
- name: Checkout repo
uses: actions/checkout@v2
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ temp/
.tmp-projections
build/
.rts2*
coverage/

typesversions
.cache
Expand Down
6 changes: 3 additions & 3 deletions docs/api/createAsyncThunk.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ The logic in the `payloadCreator` function may use any of these values as needed

An object with the following optional fields:

- `condition(arg, { getState, extra } ): boolean`: a callback that can be used to skip execution of the payload creator and all action dispatches, if desired. See [Canceling Before Execution](#canceling-before-execution) for a complete description.
- `condition(arg, { getState, extra } ): boolean | Promise<boolean>`: a callback that can be used to skip execution of the payload creator and all action dispatches, if desired. See [Canceling Before Execution](#canceling-before-execution) for a complete description.
- `dispatchConditionRejection`: if `condition()` returns `false`, the default behavior is that no actions will be dispatched at all. If you still want a "rejected" action to be dispatched when the thunk was canceled, set this flag to `true`.
- `idGenerator(): string`: a function to use when generating the `requestId` for the request sequence. Defaults to use [nanoid](./otherExports.mdx/#nanoid).
- `idGenerator(arg): string`: a function to use when generating the `requestId` for the request sequence. Defaults to use [nanoid](./otherExports.mdx/#nanoid), but you can implement your own ID generation logic.
- `serializeError(error: unknown) => any` to replace the internal `miniSerializeError` method with your own serialization logic.
- `getPendingMeta({ arg, requestId }, { getState, extra }): any`: a function to create an object that will be merged into the `pendingAction.meta` field.

Expand Down Expand Up @@ -357,7 +357,7 @@ const updateUser = createAsyncThunk(

### Canceling Before Execution

If you need to cancel a thunk before the payload creator is called, you may provide a `condition` callback as an option after the payload creator. The callback will receive the thunk argument and an object with `{getState, extra}` as parameters, and use those to decide whether to continue or not. If the execution should be canceled, the `condition` callback should return a literal `false` value:
If you need to cancel a thunk before the payload creator is called, you may provide a `condition` callback as an option after the payload creator. The callback will receive the thunk argument and an object with `{getState, extra}` as parameters, and use those to decide whether to continue or not. If the execution should be canceled, the `condition` callback should return a literal `false` value or a promise that should resolve to `false`. If a promise is returned, the thunk waits for it to get fulfilled before dispatching the `pending` action, otherwise it proceeds with dispatching synchronously.

```js
const fetchUserById = createAsyncThunk(
Expand Down
15 changes: 15 additions & 0 deletions docs/api/createReducer.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,21 @@ so we recommend the "builder callback" notation in most cases.

[params](docblock://createReducer.ts?token=createReducer&overload=1)

### Returns

The generated reducer function.

The reducer will have a `getInitialState` function attached that will return the initial state when called. This may be useful for tests or usage with React's `useReducer` hook:

```js
const counterReducer = createReducer(0, {
increment: (state, action) => state + action.payload,
decrement: (state, action) => state - action.payload,
})

console.log(counterReducer.getInitialState()) // 0
```

### Example Usage

[examples](docblock://createReducer.ts?token=createReducer&overload=1)
Expand Down
5 changes: 4 additions & 1 deletion docs/api/createSlice.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ function createSlice({

The initial state value for this slice of state.

This may also be a "lazy initializer" function, which should return an initial state value when called. This will be used whenever the reducer is called with `undefined` as its state value, and is primarily useful for cases like reading initial state from `localStorage`.

### `name`

A string name for this slice of state. Generated action type constants will use this as a prefix.
Expand Down Expand Up @@ -196,7 +198,8 @@ We recommend using the `builder callback` API as the default, especially if you
name : string,
reducer : ReducerFunction,
actions : Record<string, ActionCreator>,
caseReducers: Record<string, CaseReducer>
caseReducers: Record<string, CaseReducer>.
getInitialState: () => State
}
```

Expand Down
2 changes: 2 additions & 0 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"graphql-request": "^3.4.0",
"immutable": "^3.8.2",
"nanoid": "^3.1.23",
"next-redux-wrapper": "^7.0.5",
"redux-persist": "^6.0.0",
"rxjs": "^6.6.2"
}
}
28 changes: 25 additions & 3 deletions docs/rtk-query/api/createApi.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ export const { useGetPokemonByNameQuery } = pokemonApi
```ts no-transpile
baseQuery(args: InternalQueryArgs, api: BaseQueryApi, extraOptions?: DefinitionExtraOptions): any;
endpoints(build: EndpointBuilder<InternalQueryArgs, TagTypes>): Definitions;
extractRehydrationInfo?: (
action: AnyAction,
{
reducerPath,
}: {
reducerPath: ReducerPath
}
) =>
| undefined
| CombinedState<Definitions, TagTypes, ReducerPath>
tagTypes?: readonly TagTypes[];
reducerPath?: ReducerPath;
serializeQueryArgs?: SerializeQueryArgs<InternalQueryArgs>;
Expand Down Expand Up @@ -144,7 +154,8 @@ export type QueryDefinition<
/* transformResponse only available with `query`, not `queryFn` */
transformResponse?(
baseQueryReturnValue: BaseQueryResult<BaseQuery>,
meta: BaseQueryMeta<BaseQuery>
meta: BaseQueryMeta<BaseQuery>,
arg: QueryArg
): ResultType | Promise<ResultType>

extraOptions?: BaseQueryExtraOptions<BaseQuery>
Expand Down Expand Up @@ -211,7 +222,8 @@ export type MutationDefinition<
/* transformResponse only available with `query`, not `queryFn` */
transformResponse?(
baseQueryReturnValue: BaseQueryResult<BaseQuery>,
meta: BaseQueryMeta<BaseQuery>
meta: BaseQueryMeta<BaseQuery>,
arg: QueryArg
): ResultType | Promise<ResultType>

extraOptions?: BaseQueryExtraOptions<BaseQuery>
Expand Down Expand Up @@ -289,6 +301,15 @@ export const { endpoints, reducerPath, reducer, middleware } = api
// see `createApi` overview for _all exports_
```

### `extractRehydrationInfo`

[summary](docblock://query/createApi.ts?token=CreateApiOptions.extractRehydrationInfo)

[examples](docblock://query/createApi.ts?token=CreateApiOptions.extractRehydrationInfo)

See also [Server Side Rendering](../usage/server-side-rendering.mdx) and
[Persistence and Rehydration](../usage/persistence-and-rehydration.mdx).

### `tagTypes`

[summary](docblock://query/createApi.ts?token=CreateApiOptions.tagTypes)
Expand Down Expand Up @@ -406,7 +427,8 @@ In some cases, you may want to manipulate the data returned from a query before
See also [Customizing query responses with `transformResponse`](../usage/customizing-queries.mdx#customizing-query-responses-with-transformresponse)

```ts title="Unpack a deeply nested collection" no-transpile
transformResponse: (response) => response.some.deeply.nested.collection
transformResponse: (response, meta, arg) =>
response.some.deeply.nested.collection
```

### `extraOptions`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
---
id: cache-management-utils
title: 'API Slices: Cache Management'
sidebar_label: Cache Management Utils
id: api-slice-utils
title: 'API Slices: Utilities'
sidebar_label: API Slice Utilities
hide_title: true
---

&nbsp;

# API Slices: Cache Management Utilities
# API Slices: Utilities

The API slice object includes cache management utilities that are used for implementing [optimistic updates](../../usage/manual-cache-updates.mdx#optimistic-updates). These are included in a `util` field inside the slice object.
The API slice object includes various utilities that can be used for cache management,
such as implementing [optimistic updates](../../usage/manual-cache-updates.mdx#optimistic-updates),
as well implementing [server side rendering](../../usage/server-side-rendering.mdx).

These are included in a `util` field inside the slice object.

### `updateQueryData`

Expand Down Expand Up @@ -244,3 +248,54 @@ Note that [hooks](./hooks.mdx) also track state in local component state and mig
```ts no-transpile
dispatch(api.util.resetApiState())
```

## `getRunningOperationPromises`

#### Signature

```ts no-transpile
getRunningOperationPromises: () => Array<Promise<unknown>>
```

#### Description

A function that returns all promises for running queries and mutations.

This is useful for SSR scenarios to await everything triggered in any way, including via hook calls,
or manually dispatching `initiate` actions.

```ts no-transpile title="Awaiting all currently running queries & mutations example"
await Promise.all(api.util.getRunningOperationPromises())
```

## `getRunningOperationPromise`

#### Signature

```ts no-transpile
getRunningOperationPromise: <EndpointName extends QueryKeys<Definitions>>(
endpointName: EndpointName,
args: QueryArgFrom<Definitions[EndpointName]>
) =>
| QueryActionCreatorResult<Definitions[EndpointName]>
| undefined

getRunningOperationPromise: <EndpointName extends MutationKeys<Definitions>>(
endpointName: EndpointName,
fixedCacheKeyOrRequestId: string
) =>
| MutationActionCreatorResult<Definitions[EndpointName]>
| undefined
```
#### Description
A function that returns a single promise for a given endpoint name + argument combination,
if it is currently running. If it is not currently running, the function returns `undefined`.
When used with mutation endpoints, it accepts a [fixed cache key](./hooks.mdx#signature-1)
or request ID rather than the argument.
This is primarily added to add experimental support for suspense in the future.
It enables writing custom hooks that look up if RTK Query has already got a running promise
for a certain endpoint/argument combination, and retrieving that promise to `throw` it.
55 changes: 38 additions & 17 deletions docs/rtk-query/api/created-api/hooks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,8 @@ type UseQueryOptions = {
type UseQueryResult<T> = {
// Base query state
originalArgs?: unknown // Arguments passed to the query
data?: T // Returned result if present
data?: T // The latest returned result regardless of hook arg, if present
currentData?: T // The latest returned result for the current hook arg, 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
Expand Down Expand Up @@ -314,20 +315,22 @@ type UseMutation = (
type UseMutationStateOptions = {
// A method to determine the contents of `UseMutationResult`
selectFromResult?: (result: UseMutationStateDefaultResult) => any
// A string used to enable shared results across hook instances which have the same key
fixedCacheKey?: string
}

type UseMutationTrigger<T> = (
arg: any
) => Promise<{ data: T } | { error: BaseQueryError | SerializedError }> & {
type UseMutationTrigger<T> = (arg: any) => Promise<
{ data: T } | { error: BaseQueryError | SerializedError }
> & {
requestId: string // A string generated by RTK Query
abort: () => void // A method to cancel the mutation promise
unwrap: () => Promise<T> // A method to unwrap the mutation call and provide the raw response/error
unsubscribe: () => void // A method to manually unsubscribe from the mutation call
reset: () => void // A method to manually unsubscribe from the mutation call and reset the result to the uninitialized state
}

type UseMutationResult<T> = {
// Base query state
originalArgs?: unknown // Arguments passed to the latest mutation call
originalArgs?: unknown // Arguments passed to the latest mutation call. Not available if using the `fixedCacheKey` option
data?: T // Returned result if present
error?: unknown // Error result if present
endpointName?: string // The name of the given endpoint for the mutation
Expand All @@ -339,6 +342,8 @@ type UseMutationResult<T> = {
isSuccess: boolean // Mutation has data from a successful call
isError: boolean // Mutation is currently in an "error" state
startedTimeStamp?: number // Timestamp for when the latest mutation was initiated

reset: () => void // A method to manually unsubscribe from the mutation call and reset the result to the uninitialized state
}
```
Expand All @@ -356,11 +361,16 @@ selectFromResult: () => ({})
- **Parameters**
- `options`: A set of options that control the subscription behavior of the hook
- `options`: A set of options that control the subscription behavior of the hook:
- `selectFromResult`: A callback that can be used to customize the mutation result returned as the second item in the tuple
- `fixedCacheKey`: An optional string used to enable shared results across hook instances
- **Returns**: A tuple containing:
- `trigger`: A function that triggers an update to the data based on the provided argument. The trigger function returns a promise with the properties shown above that may be used to handle the behavior of the promise
- `mutationState`: A query status object containing the current loading state and metadata about the request, or the values returned by the `selectFromResult` option where applicable
- `mutationState`: A query status object containing the current loading state and metadata about the request, or the values returned by the `selectFromResult` option where applicable.
Additionally, this object will contain
- a `reset` method to reset the hook back to it's original state and remove the current result from the cache
- an `originalArgs` property that contains the argument passed to the last call of the `trigger` function.
#### Description
Expand Down Expand Up @@ -388,7 +398,8 @@ type UseQueryStateOptions = {
type UseQueryStateResult<T> = {
// Base query state
originalArgs?: unknown // Arguments passed to the query
data?: T // Returned result if present
data?: T // The latest returned result regardless of hook arg, if present
currentData?: T // The latest returned result for the current hook arg, 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
Expand Down Expand Up @@ -459,9 +470,8 @@ type UseQuerySubscriptionResult = {
## `useLazyQuery`
```ts title="Accessing a useLazyQuery hook" no-transpile
const [trigger, result, lastPromiseInfo] = api.endpoints.getPosts.useLazyQuery(
options
)
const [trigger, result, lastPromiseInfo] =
api.endpoints.getPosts.useLazyQuery(options)
// or
const [trigger, result, lastPromiseInfo] = api.useLazyGetPostsQuery(options)
```
Expand All @@ -480,12 +490,24 @@ type UseLazyQueryOptions = {
selectFromResult?: (result: UseQueryStateDefaultResult) => any
}

type UseLazyQueryTrigger = (arg: any) => void
type UseLazyQueryTrigger<T> = (arg: any) => Promise<
QueryResultSelectorResult
> & {
arg: unknown // Whatever argument was provided to the query
requestId: string // A string generated by RTK Query
subscriptionOptions: SubscriptionOptions // The values used for the query subscription
abort: () => void // A method to cancel the query promise
unwrap: () => Promise<T> // A method to unwrap the query call and provide the raw response/error
unsubscribe: () => void // A method used to manually unsubscribe from the query results
refetch: () => void // A method used to re-run the query. In most cases when using a lazy query, you will never use this and should prefer to call the trigger again.
updateSubscriptionOptions: (options: SubscriptionOptions) () => void // A method used to update the subscription options (eg. pollingInterval)
}

type UseQueryStateResult<T> = {
// Base query state
originalArgs?: unknown // Arguments passed to the query
data?: T // Returned result if present
data?: T // The latest returned result regardless of trigger arg, if present
currentData?: T // The latest returned result for the trigger arg, 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
Expand Down Expand Up @@ -520,9 +542,8 @@ type UseLazyQueryLastPromiseInfo = {
## `useLazyQuerySubscription`
```ts title="Accessing a useLazyQuerySubscription hook" no-transpile
const [trigger, lastArg] = api.endpoints.getPosts.useLazyQuerySubscription(
options
)
const [trigger, lastArg] =
api.endpoints.getPosts.useLazyQuerySubscription(options)
```

#### Signature
Expand Down
Loading

0 comments on commit db0d7dc

Please sign in to comment.