@@ -76,39 +76,75 @@ const PostList = () => {
76
76
};
77
77
```
78
78
79
- ## Pagination and Caching
80
-
81
- If you have caching enabled for your paginated queries, it maybe a good idea to invalidate the `LIST` cache as well when you do a `delete` mutation.
79
+ ### Automated Re-fetching of Paginated Queries
80
+
81
+ It is a common use-case to utilize tag invalidation to perform
82
+ [automated re-fetching](./automated-refetching.mdx) with RTK Query.
83
+
84
+ A potential pitfall when combining this with pagination is that your paginated query may only
85
+ provide a _partial_ list at any given time, and hence not `provide` tags for entity IDs that
86
+ fall on pages which aren't currently shown. If a specific entity is deleted that falls on an
87
+ earlier page, the paginated query will not be providing a tag for that specific ID, and will
88
+ not be invalidated to trigger re-fetching data. As a result, items on the current page that
89
+ should shift one item up will not have done so, and the total count of items and/or pages
90
+ may be incorrect.
91
+
92
+ A strategy to overcome this is to ensure that the `delete` mutation always `invalidates` the
93
+ paginated query, even if the deleted item is not _currently_ provided on that page. We can
94
+ leverage the concept of
95
+ [advanced invalidation with abstract tag ids](./automated-refetching.mdx#advanced-invalidation-with-abstract-tag-ids)
96
+ to do this by `providing` a `'Posts'` tag with the `'PARTIAL-LIST'` ID in our paginated query,
97
+ and `invalidating` that corresponding tag for any mutation that should affect it.
82
98
83
99
```ts title="Example of invalidating cache for paginated queries"
84
- // file: types.ts noEmit
85
- export interface Post {
100
+ // file: api.ts
101
+ import { createApi , fetchBaseQuery } from '@reduxjs/toolkit/query/react'
102
+ interface Post {
86
103
id : number
87
104
name : string
88
105
}
106
+ interface ListResponse<T > {
107
+ page : number
108
+ per_page : number
109
+ total : number
110
+ total_pages : number
111
+ data : T []
112
+ }
89
113
90
- // file: api.ts
91
- // Or from '@reduxjs/toolkit/query/react'
92
- import { createApi , fetchBaseQuery } from '@reduxjs/toolkit/query/react'
93
- import { Post } from './types'
94
-
95
- export const postApi = createApi({
96
- reducerPath : ' postsApi' ,
97
- baseQuery : fetchBaseQuery ({ baseUrl: ' /' }),
98
- tagTypes : [' Posts' ],
114
+ export const postApi = createApi({
115
+ reducerPath : ' postsApi' ,
116
+ baseQuery : fetchBaseQuery ({ baseUrl: ' /' }),
117
+ tagTypes : [' Posts' ],
99
118
endpoints : (build ) => ({
100
- deletePost: build .mutation <{ success: boolean ; id: number }, number >({
101
- query(id ) {
102
- return {
103
- url: ` post/${id } ` ,
104
- method: ' DELETE' ,
105
- }
106
- },
107
- // Invalidates queries that subscribe to this Post `id` as well as the `LIST`.
119
+ listPosts: build .query <ListResponse <Post >, number | void >({
120
+ query : (page = 1 ) => ` posts?page=${page } ` ,
121
+ // highlight-start
122
+ providesTags : (result , error , page ) =>
123
+ result
124
+ ? [
125
+ // Provides a tag for each post in the current page,
126
+ // as well as the 'PARTIAL-LIST' tag.
127
+ ... result .data .map (({ id }) => ({ type: ' Posts' as const , id })),
128
+ { type: ' Posts' , id: ' PARTIAL-LIST' },
129
+ ]
130
+ : [{ type: ' Posts' , id: ' PARTIAL-LIST' }],
131
+ // highlight-end
132
+ }),
133
+ deletePost: build .mutation <{ success: boolean ; id: number }, number >({
134
+ query(id ) {
135
+ return {
136
+ url: ` post/${id } ` ,
137
+ method: ' DELETE' ,
138
+ }
139
+ },
140
+ // Invalidates the tag for this Post `id`, as well as the `PARTIAL-LIST` tag,
141
+ // causing the `listPosts` query to re-fetch if a component is subscribed to the query.
142
+ // highlight-start
108
143
invalidatesTags : (result , error , id ) => [
109
- { type: " Posts" , id },
110
- { type: " Posts" , id: " LIST" },
144
+ { type: ' Posts' , id },
145
+ { type: ' Posts' , id: ' PARTIAL- LIST' },
111
146
],
147
+ // highlight-end
112
148
}),
113
149
}),
114
150
} )
0 commit comments