Skip to content

Commit 037e772

Browse files
authored
Merge pull request #1133 from Shrugsy/docs/extend-onQueryStarted-documentation
2 parents cb3eaf2 + ead8694 commit 037e772

File tree

11 files changed

+154
-28
lines changed

11 files changed

+154
-28
lines changed

docs/rtk-query/api/createApi.mdx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,46 @@ async function onQueryStarted(
484484
): Promise<void>
485485
```
486486

487+
```ts title="onQueryStarted query lifecycle example"
488+
// file: notificationsSlice.ts noEmit
489+
export const messageCreated = (msg: string) => ({
490+
type: 'notifications/messageCreated',
491+
payload: msg,
492+
})
493+
494+
// file: api.ts
495+
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
496+
import { messageCreated } from './notificationsSlice'
497+
498+
export interface Post {
499+
id: number
500+
name: string
501+
}
502+
503+
const api = createApi({
504+
baseQuery: fetchBaseQuery({
505+
baseUrl: '/',
506+
}),
507+
endpoints: (build) => ({
508+
getPost: build.query<Post, number>({
509+
query: (id) => `post/${id}`,
510+
async onQueryStarted(id, { dispatch, queryFulfilled }) {
511+
// `onStart` side-effect
512+
dispatch(messageCreated('Fetching post...'))
513+
try {
514+
const { data } = await queryFulfilled
515+
// `onSuccess` side-effect
516+
dispatch(messageCreated('Post received!'))
517+
} catch (err) {
518+
// `onError` side-effect
519+
dispatch(messageCreated('Error fetching post!'))
520+
}
521+
},
522+
}),
523+
}),
524+
})
525+
```
526+
487527
### `onCacheEntryAdded`
488528

489529
_(optional)_

docs/rtk-query/usage-with-typescript.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ const api = createApi({
216216
getPost: build.query<Post, number>({
217217
// inferred as `number` from the `QueryArg` type
218218
// v
219-
query: (id) => `posts/${id}`,
219+
query: (id) => `post/${id}`,
220220
// An explicit type must be provided to the raw result that the query returns
221221
// when using `transformResponse`
222222
// v
@@ -452,7 +452,7 @@ export const api = createApi({
452452
// Query argument is required to be `number`, and can't be `undefined`
453453
// V
454454
getPost: build.query<Post, number>({
455-
query: (id) => `posts/${id}`,
455+
query: (id) => `post/${id}`,
456456
}),
457457
}),
458458
})

docs/rtk-query/usage/automated-refetching.mdx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,14 @@ const api = createApi({
8787
}),
8888
addPost: build.mutation<Post, Omit<Post, 'id'>>({
8989
query: (body) => ({
90-
url: 'posts',
90+
url: 'post',
9191
method: 'POST',
9292
body,
9393
}),
9494
}),
9595
editPost: build.mutation<Post, Partial<Post> & Pick<Post, 'id'>>({
9696
query: (body) => ({
97-
url: `posts/${body.id}`,
97+
url: `post/${body.id}`,
9898
method: 'POST',
9999
body,
100100
}),
@@ -160,7 +160,7 @@ const api = createApi({
160160
}),
161161
editPost: build.mutation<Post, Partial<Post> & Pick<Post, 'id'>>({
162162
query: (body) => ({
163-
url: `posts/${body.id}`,
163+
url: `post/${body.id}`,
164164
method: 'POST',
165165
body,
166166
}),
@@ -210,14 +210,14 @@ const api = createApi({
210210
}),
211211
addPost: build.mutation<Post, Omit<Post, 'id'>>({
212212
query: (body) => ({
213-
url: 'posts',
213+
url: 'post',
214214
method: 'POST',
215215
body,
216216
}),
217217
}),
218218
editPost: build.mutation<Post, Partial<Post> & Pick<Post, 'id'>>({
219219
query: (body) => ({
220-
url: `posts/${body.id}`,
220+
url: `post/${body.id}`,
221221
method: 'POST',
222222
body,
223223
}),
@@ -275,7 +275,7 @@ const api = createApi({
275275
}),
276276
addPost: build.mutation<Post, Omit<Post, 'id'>>({
277277
query: (body) => ({
278-
url: 'posts',
278+
url: 'post',
279279
method: 'POST',
280280
body,
281281
}),
@@ -285,7 +285,7 @@ const api = createApi({
285285
}),
286286
editPost: build.mutation<Post, Partial<Post> & Pick<Post, 'id'>>({
287287
query: (body) => ({
288-
url: `posts/${body.id}`,
288+
url: `post/${body.id}`,
289289
method: 'POST',
290290
body,
291291
}),
@@ -355,15 +355,15 @@ const api = createApi({
355355
}),
356356
addPost: build.mutation<Post, Omit<Post, 'id'>>({
357357
query: (body) => ({
358-
url: 'posts',
358+
url: 'post',
359359
method: 'POST',
360360
body,
361361
}),
362362
invalidatesTags: ['Post'],
363363
}),
364364
editPost: build.mutation<Post, Partial<Post> & Pick<Post, 'id'>>({
365365
query: (body) => ({
366-
url: `posts/${body.id}`,
366+
url: `post/${body.id}`,
367367
method: 'POST',
368368
body,
369369
}),
@@ -647,14 +647,14 @@ export const api = createApi({
647647
}),
648648
addPost: build.mutation<Post, Partial<Post>>({
649649
query: (body) => ({
650-
url: `posts`,
650+
url: `post`,
651651
method: 'POST',
652652
body,
653653
}),
654654
invalidatesTags: ['Posts'],
655655
}),
656656
getPost: build.query<Post, number>({
657-
query: (id) => `posts/${id}`,
657+
query: (id) => `post/${id}`,
658658
providesTags: (result, error, id) => [{ type: 'Posts', id }],
659659
}),
660660
}),
@@ -720,15 +720,15 @@ export const api = createApi({
720720
addPost: build.mutation<Post, Partial<Post>>({
721721
query(body) {
722722
return {
723-
url: `posts`,
723+
url: `post`,
724724
method: 'POST',
725725
body,
726726
}
727727
},
728728
invalidatesTags: [{ type: 'Posts', id: 'LIST' }],
729729
}),
730730
getPost: build.query<Post, number>({
731-
query: (id) => `posts/${id}`,
731+
query: (id) => `post/${id}`,
732732
providesTags: (result, error, id) => [{ type: 'Posts', id }],
733733
}),
734734
}),

docs/rtk-query/usage/customizing-queries.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ export const api = createApi({
427427
query: () => ({ url: 'posts' }),
428428
}),
429429
getPost: build.query<PostsResponse, string>({
430-
query: (id) => ({ url: `posts/${id}` }),
430+
query: (id) => ({ url: `post/${id}` }),
431431
extraOptions: { maxRetries: 8 }, // You can override the retry behavior on each endpoint
432432
}),
433433
}),

docs/rtk-query/usage/mutations.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ export const postApi = createApi({
182182
addPost: build.mutation<Post, Partial<Post>>({
183183
query(body) {
184184
return {
185-
url: `posts`,
185+
url: `poss`,
186186
method: 'POST',
187187
body,
188188
}
@@ -192,14 +192,14 @@ export const postApi = createApi({
192192
invalidatesTags: [{ type: 'Posts', id: 'LIST' }],
193193
}),
194194
getPost: build.query<Post, number>({
195-
query: (id) => `posts/${id}`,
195+
query: (id) => `post/${id}`,
196196
providesTags: (result, error, id) => [{ type: 'Posts', id }],
197197
}),
198198
updatePost: build.mutation<Post, Partial<Post>>({
199199
query(data) {
200200
const { id, ...body } = data
201201
return {
202-
url: `posts/${id}`,
202+
url: `post/${id}`,
203203
method: 'PUT',
204204
body,
205205
}
@@ -211,7 +211,7 @@ export const postApi = createApi({
211211
deletePost: build.mutation<{ success: boolean; id: number }, number>({
212212
query(id) {
213213
return {
214-
url: `posts/${id}`,
214+
url: `post/${id}`,
215215
method: 'DELETE',
216216
}
217217
},

docs/rtk-query/usage/optimistic-updates.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ const api = createApi({
6464
})
6565
```
6666

67-
or, if you prefer the slighty shorter version with `.catch`
67+
or, if you prefer the slightly shorter version with `.catch`
6868

6969
```diff
7070
- async onQueryStarted({ id, ...patch }, { dispatch, queryFulfilled }) {

src/query/core/buildMiddleware/queryLifecycle.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,44 @@ declare module '../../endpointDefinitions' {
7373
BaseQuery extends BaseQueryFn,
7474
ReducerPath extends string = string
7575
> {
76+
/**
77+
* A function that is called when the individual query is started. The function is called with a lifecycle api object containing properties such as `queryFulfilled`, allowing code to be run when a query is started, when it succeeds, and when it fails (i.e. throughout the lifecycle of an individual query/mutation call).
78+
*
79+
* Can be used to perform side-effects throughout the lifecycle of the query.
80+
*
81+
* @example
82+
* ```ts
83+
* import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
84+
* import { messageCreated } from './notificationsSlice
85+
* export interface Post {
86+
* id: number
87+
* name: string
88+
* }
89+
*
90+
* const api = createApi({
91+
* baseQuery: fetchBaseQuery({
92+
* baseUrl: '/',
93+
* }),
94+
* endpoints: (build) => ({
95+
* getPost: build.query<Post, number>({
96+
* query: (id) => `post/${id}`,
97+
* async onQueryStarted(id, { dispatch, queryFulfilled }) {
98+
* // `onStart` side-effect
99+
* dispatch(messageCreated('Fetching posts...'))
100+
* try {
101+
* const { data } = await queryFulfilled
102+
* // `onSuccess` side-effect
103+
* dispatch(messageCreated('Posts received!'))
104+
* } catch (err) {
105+
* // `onError` side-effect
106+
* dispatch(messageCreated('Error fetching posts!'))
107+
* }
108+
* }
109+
* }),
110+
* }),
111+
* })
112+
* ```
113+
*/
76114
onQueryStarted?(
77115
arg: QueryArg,
78116
api: QueryLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath>
@@ -86,6 +124,54 @@ declare module '../../endpointDefinitions' {
86124
BaseQuery extends BaseQueryFn,
87125
ReducerPath extends string = string
88126
> {
127+
/**
128+
* A function that is called when the individual mutation is started. The function is called with a lifecycle api object containing properties such as `queryFulfilled`, allowing code to be run when a query is started, when it succeeds, and when it fails (i.e. throughout the lifecycle of an individual query/mutation call).
129+
*
130+
* Can be used for `optimistic updates`.
131+
*
132+
* @example
133+
*
134+
* ```ts
135+
* import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
136+
* export interface Post {
137+
* id: number
138+
* name: string
139+
* }
140+
*
141+
* const api = createApi({
142+
* baseQuery: fetchBaseQuery({
143+
* baseUrl: '/',
144+
* }),
145+
* tagTypes: ['Post'],
146+
* endpoints: (build) => ({
147+
* getPost: build.query<Post, number>({
148+
* query: (id) => `post/${id}`,
149+
* providesTags: ['Post'],
150+
* }),
151+
* updatePost: build.mutation<void, Pick<Post, 'id'> & Partial<Post>>({
152+
* query: ({ id, ...patch }) => ({
153+
* url: `post/${id}`,
154+
* method: 'PATCH',
155+
* body: patch,
156+
* }),
157+
* invalidatesTags: ['Post'],
158+
* async onQueryStarted({ id, ...patch }, { dispatch, queryFulfilled }) {
159+
* const patchResult = dispatch(
160+
* api.util.updateQueryData('getPost', id, (draft) => {
161+
* Object.assign(draft, patch)
162+
* })
163+
* )
164+
* try {
165+
* await queryFulfilled
166+
* } catch {
167+
* patchResult.undo()
168+
* }
169+
* },
170+
* }),
171+
* }),
172+
* })
173+
* ```
174+
*/
89175
onQueryStarted?(
90176
arg: QueryArg,
91177
api: MutationLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath>

src/query/retry.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ const retryWithBackoff: BaseQueryEnhancer<
9999
* query: () => ({ url: 'posts' }),
100100
* }),
101101
* getPost: build.query<PostsResponse, string>({
102-
* query: (id) => ({ url: `posts/${id}` }),
102+
* query: (id) => ({ url: `post/${id}` }),
103103
* extraOptions: { maxRetries: 8 }, // You can override the retry behavior on each endpoint
104104
* }),
105105
* }),

src/query/tests/buildHooks.test.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,7 +1443,7 @@ describe('hooks with createApi defaults set', () => {
14431443
return res(ctx.json(posts))
14441444
}),
14451445
rest.put<Partial<Post>>(
1446-
'http://example.com/posts/:id',
1446+
'http://example.com/post/:id',
14471447
(req, res, ctx) => {
14481448
const id = Number(req.params.id)
14491449
const idx = posts.findIndex((post) => post.id === id)
@@ -1463,7 +1463,7 @@ describe('hooks with createApi defaults set', () => {
14631463
return res(ctx.json(posts))
14641464
}
14651465
),
1466-
rest.post('http://example.com/posts', (req, res, ctx) => {
1466+
rest.post('http://example.com/post', (req, res, ctx) => {
14671467
let post = req.body as Omit<Post, 'id'>
14681468
startingId += 1
14691469
posts.concat({
@@ -1497,15 +1497,15 @@ describe('hooks with createApi defaults set', () => {
14971497
}),
14981498
updatePost: build.mutation<Post, Partial<Post>>({
14991499
query: ({ id, ...body }) => ({
1500-
url: `posts/${id}`,
1500+
url: `post/${id}`,
15011501
method: 'PUT',
15021502
body,
15031503
}),
15041504
invalidatesTags: (result, error, { id }) => [{ type: 'Posts', id }],
15051505
}),
15061506
addPost: build.mutation<Post, Partial<Post>>({
15071507
query: (body) => ({
1508-
url: `posts`,
1508+
url: `post`,
15091509
method: 'POST',
15101510
body,
15111511
}),

src/query/tests/mocks/server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export const server = setupServer(
5454
return res(ctx.json({ id }))
5555
}),
5656
rest.get<Post, any, { id: number }>(
57-
'http://example.com/posts/:id',
57+
'http://example.com/post/:id',
5858
(req, res, ctx) => {
5959
return res(ctx.json(posts[req.params.id]))
6060
}

0 commit comments

Comments
 (0)