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

Merge 1.9.4/5 into v2.0-integration #3375

Merged
merged 31 commits into from
Apr 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
184fedd
Fix global `responseHandler` being used in `fetchBaseQuery`
praxxis Jan 30, 2023
cb611a0
enable enhanceEndpoints.transformResponse to override ResultType
dmitrigrabov Jan 30, 2023
ea8081f
create EnhancerArray class for proper inference of enhancer extensions
Feb 24, 2023
9604e73
add state extensions from enhancers
Feb 24, 2023
5ad74aa
update docs usage
Feb 24, 2023
3a4ef1f
update to latest remark-typescript-tools
Mar 30, 2023
3ed1aad
add no-transpile for all TSX snippets (matches previous behaviour)
Apr 2, 2023
d746bee
no transpile docblocks too
Apr 2, 2023
98d7dda
reset internalState.currentSubscriptions on `resetApiState`
phryneas Apr 5, 2023
2571718
Minor typo fix
chmac Apr 6, 2023
ab48501
Merge pull request #3331 from chmac/patch-1
markerikson Apr 6, 2023
b9c3ef4
Add a note about timing #2435
chmac Apr 7, 2023
23a78ca
Merge pull request #3334 from chmac/patch-2
markerikson Apr 7, 2023
933502c
Use original instead of immer draft for perf
Mar 15, 2023
53df220
Merge pull request #3270 from GeorchW/copywithstructuralsharing-perf
markerikson Apr 16, 2023
8962cef
Merge pull request #2953 from dmitrigrabov/use-transformed-response-r…
markerikson Apr 16, 2023
8232827
Merge pull request #3137 from praxxis/global-responsehandler
markerikson Apr 16, 2023
ef8480b
Bump deps
markerikson Apr 16, 2023
cc9d416
Merge pull request #3333 from reduxjs/pr/fix-3119
markerikson Apr 17, 2023
a9057c6
Mark `subscriptionsUpdated` as autobatched
markerikson Apr 17, 2023
2282f60
Merge pull request #3364 from reduxjs/bugfix/autobatch-actions
markerikson Apr 17, 2023
18bc6bc
Release 1.9.4
markerikson Apr 17, 2023
811dd47
Fix typo
n-ii-ma Apr 17, 2023
eb586b6
Merge pull request #3366 from n-ii-ma/patch-1
markerikson Apr 17, 2023
482270e
add isAction helper function, and ensure listener middleware only run…
Apr 17, 2023
0c6cd6e
add test
Apr 17, 2023
ebe1777
Merge pull request #3311 from EskiMojo14/remark-typescript-update
markerikson Apr 18, 2023
da3f6ed
Merge pull request #3372 from EskiMojo14/listener-action
markerikson Apr 18, 2023
1f87ac2
Merge pull request #3207 from EskiMojo14/enhancer-array
markerikson Apr 18, 2023
d3bb412
Release 1.9.5
markerikson Apr 18, 2023
1feb9ba
Merge branch 'master' into v2.0-integration
markerikson Apr 18, 2023
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
9 changes: 5 additions & 4 deletions docs/api/configureStore.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ to the store setup for a better development experience.

```ts no-transpile
type ConfigureEnhancersCallback = (
defaultEnhancers: StoreEnhancer[]
defaultEnhancers: EnhancerArray<[StoreEnhancer]>
) => StoreEnhancer[]

interface ConfigureStoreOptions<
Expand Down Expand Up @@ -107,7 +107,8 @@ a list of the specific options that are available.
Defaults to `true`.

#### `trace`
The Redux DevTools Extension recently added [support for showing action stack traces](https://github.com/reduxjs/redux-devtools/blob/main/extension/docs/Features/Trace.md) that show exactly where each action was dispatched.

The Redux DevTools Extension recently added [support for showing action stack traces](https://github.com/reduxjs/redux-devtools/blob/main/extension/docs/Features/Trace.md) that show exactly where each action was dispatched.
Capturing the traces can add a bit of overhead, so the DevTools Extension allows users to configure whether action stack traces are captured by [setting the 'trace' argument](https://github.com/reduxjs/redux-devtools/blob/main/extension/docs/API/Arguments.md#trace).
If the DevTools are enabled by passing `true` or an object, then `configureStore` will default to enabling capturing action stack traces in development mode only.

Expand All @@ -129,7 +130,7 @@ If defined as a callback function, it will be called with the existing array of
and should return a new array of enhancers. This is primarily useful for cases where a store enhancer needs to be added
in front of `applyMiddleware`, such as `redux-first-router` or `redux-offline`.

Example: `enhancers: (defaultEnhancers) => [offline, ...defaultEnhancers]` will result in a final setup
Example: `enhancers: (defaultEnhancers) => defaultEnhancers.prepend(offline)` will result in a final setup
of `[offline, applyMiddleware, devToolsExtension]`.

## Usage
Expand Down Expand Up @@ -195,7 +196,7 @@ const preloadedState = {
visibilityFilter: 'SHOW_COMPLETED',
}

const debounceNotify = _.debounce(notify => notify());
const debounceNotify = _.debounce((notify) => notify())

const store = configureStore({
reducer,
Expand Down
4 changes: 3 additions & 1 deletion docs/api/createListenerMiddleware.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,8 @@ These methods provide the ability to write conditional logic based on future dis

Both these methods are cancellation-aware, and will throw a `TaskAbortError` if the listener instance is cancelled while paused.

Note that both `take` and `condition` will only resolve **after the next action** has been dispatched. They do not resolve immediately even if their predicate would return true for the current state.

### Child Tasks

- `fork: (executor: (forkApi: ForkApi) => T | Promise<T>) => ForkedTask<T>`: Launches a "child task" that may be used to accomplish additional work. Accepts any sync or async function as its argument, and returns a `{result, cancel}` object that can be used to check the final status and return value of the child task, or cancel it while in-progress.
Expand Down Expand Up @@ -831,7 +833,7 @@ First, you can import effect callbacks from slice files into the middleware file

```ts no-transpile title="app/listenerMiddleware.ts"
import { action1, listener1 } from '../features/feature1/feature1Slice'
import { action2, listener2 } from '../features/feature2/feature1Slice'
import { action2, listener2 } from '../features/feature2/feature2Slice'

listenerMiddleware.startListening({ actionCreator: action1, effect: listener1 })
listenerMiddleware.startListening({ actionCreator: action2, effect: listener2 })
Expand Down
15 changes: 8 additions & 7 deletions docs/rtk-query/api/created-api/endpoints.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ When dispatching an action creator, you're responsible for storing a reference t

#### Example

```tsx title="initiate query example"
```tsx no-transpile title="initiate query example"
import { useState } from 'react'
import { useAppDispatch } from './store/hooks'
import { api } from './services/api'
Expand All @@ -119,7 +119,7 @@ function App() {
}
```

```tsx title="initiate mutation example"
```tsx no-transpile title="initiate mutation example"
import { useState } from 'react'
import { useAppDispatch } from './store/hooks'
import { api, Post } from './services/api'
Expand Down Expand Up @@ -187,7 +187,7 @@ Each call to `.select(someCacheKey)` returns a _new_ selector function instance.

#### Example

```tsx title="select query example"
```tsx no-transpile title="select query example"
import { useState, useMemo } from 'react'
import { useAppDispatch, useAppSelector } from './store/hooks'
import { api } from './services/api'
Expand All @@ -198,9 +198,10 @@ function App() {
// highlight-start
// useMemo is used to only call `.select()` when required.
// Each call will create a new selector function instance
const selectPost = useMemo(() => api.endpoints.getPost.select(postId), [
postId,
])
const selectPost = useMemo(
() => api.endpoints.getPost.select(postId),
[postId]
)
const { data, isLoading } = useAppSelector(selectPost)
// highlight-end

Expand All @@ -223,7 +224,7 @@ function App() {
}
```

```tsx title="select mutation example"
```tsx no-transpile title="select mutation example"
import { useState, useMemo } from 'react'
import { skipToken } from '@reduxjs/toolkit/query'
import { useAppDispatch, useAppSelector } from './store/hooks'
Expand Down
17 changes: 8 additions & 9 deletions docs/rtk-query/usage-with-typescript.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ export const api = createApi({
export const { useGetPostQuery } = api
```

```tsx title="Using skip in a component"
```tsx no-transpile title="Using skip in a component"
import { useGetPostQuery } from './api'

function MaybePost({ id }: { id?: number }) {
Expand All @@ -486,7 +486,7 @@ While you might be able to convince yourself that the query won't be called unle

RTK Query provides a `skipToken` export which can be used as an alternative to the `skip` option in order to skip queries, while remaining type-safe. When `skipToken` is passed as the query argument to `useQuery`, `useQueryState` or `useQuerySubscription`, it provides the same effect as setting `skip: true` in the query options, while also being a valid argument in scenarios where the `arg` might be undefined otherwise.

```tsx title="Using skipToken in a component"
```tsx no-transpile title="Using skipToken in a component"
import { skipToken } from '@reduxjs/toolkit/query/react'
import { useGetPostQuery } from './api'

Expand Down Expand Up @@ -566,7 +566,7 @@ export interface SerializedError {
When using `fetchBaseQuery`, the `error` property returned from a hook will have the type `FetchBaseQueryError | SerializedError | undefined`.
If an error is present, you can access error properties after narrowing the type to either `FetchBaseQueryError` or `SerializedError`.

```tsx
```tsx no-transpile
import { api } from './services/api'

function PostDetail() {
Expand All @@ -587,10 +587,9 @@ function PostDetail() {
<div>{errMsg}</div>
</div>
)
}
else {
// you can access all properties of `SerializedError` here
return <div>{error.message}</div>
} else {
// you can access all properties of `SerializedError` here
return <div>{error.message}</div>
}
}

Expand All @@ -617,7 +616,7 @@ In order to safely access properties of the error, you must first narrow the typ
This can be done using a [type predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates)
as shown below.

```tsx title="services/helpers.ts"
```tsx no-transpile title="services/helpers.ts"
import { FetchBaseQueryError } from '@reduxjs/toolkit/query'

/**
Expand All @@ -644,7 +643,7 @@ export function isErrorWithMessage(
}
```

```tsx title="addPost.tsx"
```tsx no-transpile title="addPost.tsx"
import { useState } from 'react'
import { useSnackbar } from 'notistack'
import { api } from './services/api'
Expand Down
8 changes: 4 additions & 4 deletions docs/rtk-query/usage/automated-refetching.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ const api = createApi({
Note that for the example above, the `id` is used where possible on a successful result. In the case of an error, no result is supplied, and we still consider that it has provided the general `'Post'` tag type rather than any specific instance of that tag.

:::tip Advanced List Invalidation
In order to provide stronger control over invalidating the appropriate data, you can use an arbitrary ID such a `'LIST'` for a given tag. See [Advanced Invalidation with abstract tag IDs](#advanced-invalidation-with-abstract-tag-ids) for additional details.
In order to provide stronger control over invalidating the appropriate data, you can use an arbitrary ID such as `'LIST'` for a given tag. See [Advanced Invalidation with abstract tag IDs](#advanced-invalidation-with-abstract-tag-ids) for additional details.
:::

### Invalidating cache data
Expand Down Expand Up @@ -381,7 +381,7 @@ const api = createApi({
For the example above, rather than invalidating any tag with the type `'Post'`, calling the `editPost` mutation function will now only invalidate a tag for the provided `id`. I.e. if cached data from an endpoint does not provide a `'Post'` for that same `id`, it will remain considered as 'valid', and will not be triggered to automatically re-fetch.

:::tip Using abstract tag IDs
In order to provide stronger control over invalidating the appropriate data, you can use an arbitrary ID such a `'LIST'` for a given tag. See [Advanced Invalidation with abstract tag IDs](#advanced-invalidation-with-abstract-tag-ids) for additional details.
In order to provide stronger control over invalidating the appropriate data, you can use an arbitrary ID such as `'LIST'` for a given tag. See [Advanced Invalidation with abstract tag IDs](#advanced-invalidation-with-abstract-tag-ids) for additional details.
:::

## Tag Invalidation Behavior
Expand Down Expand Up @@ -668,7 +668,7 @@ export const api = createApi({
export const { useGetPostsQuery, useGetPostQuery, useAddPostMutation } = api
```

```tsx title="App.tsx"
```tsx no-transpile title="App.tsx"
function App() {
const { data: posts } = useGetPostsQuery()
const [addPost] = useAddPostMutation()
Expand Down Expand Up @@ -742,7 +742,7 @@ export const api = createApi({
export const { useGetPostsQuery, useAddPostMutation, useGetPostQuery } = api
```

```tsx title="App.tsx"
```tsx no-transpile title="App.tsx"
function App() {
const { data: posts } = useGetPostsQuery()
const [addPost] = useAddPostMutation()
Expand Down
4 changes: 2 additions & 2 deletions docs/rtk-query/usage/cache-behavior.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ Calling the `refetch` function will force refetch the associated query.

Alternatively, you can dispatch the `initiate` thunk action for an endpoint, passing the option `forceRefetch: true` to the thunk action creator for the same effect.

```tsx title="Force refetch example"
```tsx no-transpile title="Force refetch example"
import { useDispatch } from 'react-redux'
import { useGetPostsQuery } from './api'

Expand Down Expand Up @@ -197,7 +197,7 @@ export const api = createApi({
})
```

```tsx title="Forcing refetch on component mount"
```tsx no-transpile title="Forcing refetch on component mount"
import { useGetPostsQuery } from './api'

const Component = () => {
Expand Down
25 changes: 12 additions & 13 deletions docs/rtk-query/usage/error-handling.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ If your query or mutation happens to throw an error when using [fetchBaseQuery](

### Error Display Examples

```tsx title="Query Error"
```tsx no-transpile title="Query Error"
function PostsList() {
const { data, error } = useGetPostsQuery()

Expand All @@ -28,7 +28,7 @@ function PostsList() {
}
```

```tsx title="Mutation Error"
```tsx no-transpile title="Mutation Error"
function AddPost() {
const [addPost, { error }] = useAddPostMutation()

Expand All @@ -52,7 +52,7 @@ addPost({ id: 1, name: 'Example' })

:::

```tsx title="Manually selecting an error"
```tsx no-transpile title="Manually selecting an error"
function PostsList() {
const { error } = useSelector(api.endpoints.getPosts.select())

Expand Down Expand Up @@ -88,15 +88,14 @@ import { toast } from 'your-cool-library'
/**
* Log a warning and show a toast!
*/
export const rtkQueryErrorLogger: Middleware = (api: MiddlewareAPI) => (
next
) => (action) => {
// RTK Query uses `createAsyncThunk` from redux-toolkit under the hood, so we're able to utilize these matchers!
if (isRejectedWithValue(action)) {
console.warn('We got a rejected action!')
toast.warn({ title: 'Async error!', message: action.error.data.message })
export const rtkQueryErrorLogger: Middleware =
(api: MiddlewareAPI) => (next) => (action) => {
// RTK Query uses `createAsyncThunk` from redux-toolkit under the hood, so we're able to utilize these matchers!
if (isRejectedWithValue(action)) {
console.warn('We got a rejected action!')
toast.warn({ title: 'Async error!', message: action.error.data.message })
}

return next(action)
}

return next(action)
}
```
2 changes: 1 addition & 1 deletion docs/rtk-query/usage/manual-cache-updates.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ callback for a mutation without a good reason, as RTK Query is intended to be us
your cached data as a reflection of the server-side state.
:::

```tsx title="General manual cache update example"
```tsx no-transpile title="General manual cache update example"
import { api } from './api'
import { useAppDispatch } from './store/hooks'

Expand Down
8 changes: 4 additions & 4 deletions docs/rtk-query/usage/migrating-to-rtk-query.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ export type RootState = ReturnType<typeof store.getState>

In order to have the store accessible within our app, we will wrap our `App` component with a [`Provider`](https://react-redux.js.org/api/provider) component from `react-redux`.

```tsx title="src/index.ts"
```tsx no-transpile title="src/index.ts"
import { render } from 'react-dom'
// highlight-start
import { Provider } from 'react-redux'
Expand Down Expand Up @@ -223,9 +223,9 @@ export type RootState = {
pokemon: typeof initialPokemonSlice
}

export declare const store: EnhancedStore<RootState>
export declare const store: EnhancedStore<RootState>
export type AppDispatch = typeof store.dispatch
export declare const useAppDispatch: () => (...args: any[])=> any;
export declare const useAppDispatch: () => (...args: any[]) => any

// file: src/hooks.ts
import { useEffect } from 'react'
Expand Down Expand Up @@ -276,7 +276,7 @@ Our implementation below provides the following behaviour in the component:
- When our component is mounted, if a request for the provided pokemon name has not already been sent for the session, send the request off
- The hook always provides the latest received `data` when available, as well as the request status booleans `isUninitialized`, `isPending`, `isFulfilled` & `isRejected` in order to determine the current UI at any given moment as a function of our state.

```tsx title="src/App.tsx"
```tsx no-transpile title="src/App.tsx"
import * as React from 'react'
// highlight-start
import { useGetPokemonByNameQuery } from './hooks'
Expand Down
8 changes: 6 additions & 2 deletions docs/rtk-query/usage/mutations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,11 @@ const api = createApi({
// Pick out data and prevent nested properties in a hook or selector
transformResponse: (response: { data: Post }, meta, arg) => response.data,
// Pick out errors and prevent nested properties in a hook or selector
transformErrorResponse: (response: { status: string | number }, meta, arg) => response.status,
transformErrorResponse: (
response: { status: string | number },
meta,
arg
) => response.status,
invalidatesTags: ['Post'],
// onQueryStarted is useful for optimistic updates
// The 2nd parameter is the destructured `MutationLifecycleApi`
Expand Down Expand Up @@ -177,7 +181,7 @@ When using `fixedCacheKey`, the `originalArgs` property is not able to be shared

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 an `EditablePostName` component is rendered that allows us to edit the name of the post.

```tsx title="src/features/posts/PostDetail.tsx"
```tsx no-transpile title="src/features/posts/PostDetail.tsx"
export const PostDetail = () => {
const { id } = useParams<{ id: any }>()

Expand Down
38 changes: 19 additions & 19 deletions docs/rtk-query/usage/pagination.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -44,36 +44,35 @@ export const { useListPostsQuery } = api

### Trigger the next page by incrementing the `page` state variable

```tsx title="src/features/posts/PostsManager.tsx"
```tsx no-transpile title="src/features/posts/PostsManager.tsx"
const PostList = () => {
const [page, setPage] = useState(1);
const { data: posts, isLoading, isFetching } = useListPostsQuery(page);
const [page, setPage] = useState(1)
const { data: posts, isLoading, isFetching } = useListPostsQuery(page)

if (isLoading) {
return <div>Loading</div>;
return <div>Loading</div>
}

if (!posts?.data) {
return <div>No posts :(</div>;
return <div>No posts :(</div>
}

return (
<div>
{posts.data.map(({ id, title, status }) => (
<div key={id}>{title} - {status}</div>
))}
<button onClick={() => setPage(page - 1)} isLoading={isFetching}>
Previous
</button>
<button
onClick={() => setPage(page + 1)}
isLoading={isFetching}
>
Next
</button>
{posts.data.map(({ id, title, status }) => (
<div key={id}>
{title} - {status}
</div>
))}
<button onClick={() => setPage(page - 1)} isLoading={isFetching}>
Previous
</button>
<button onClick={() => setPage(page + 1)} isLoading={isFetching}>
Next
</button>
</div>
);
};
)
}
```

### Automated Re-fetching of Paginated Queries
Expand Down Expand Up @@ -149,6 +148,7 @@ export const postApi = createApi({
}),
})
```

## General Pagination Example

In the following example, you'll see `Loading` on the initial query, but then as you move forward we'll use the next/previous buttons as a _fetching_ indicator while any non-cached query is performed. When you go back, the cached data will be served instantaneously.
Expand Down
Loading