@@ -112,6 +112,100 @@ export function buildSlice({
112
112
>
113
113
} ) {
114
114
const resetApiState = createAction ( `${ reducerPath } /resetApiState` )
115
+
116
+ function writePendingCacheEntry (
117
+ draft : QueryState < any > ,
118
+ arg : QueryThunkArg ,
119
+ upserting : boolean ,
120
+ meta : {
121
+ arg : QueryThunkArg
122
+ requestId : string
123
+ // requestStatus: 'pending'
124
+ } & { startedTimeStamp : number } ,
125
+ ) {
126
+ draft [ arg . queryCacheKey ] ??= {
127
+ status : QueryStatus . uninitialized ,
128
+ endpointName : arg . endpointName ,
129
+ }
130
+
131
+ updateQuerySubstateIfExists ( draft , arg . queryCacheKey , ( substate ) => {
132
+ substate . status = QueryStatus . pending
133
+
134
+ substate . requestId =
135
+ upserting && substate . requestId
136
+ ? // for `upsertQuery` **updates**, keep the current `requestId`
137
+ substate . requestId
138
+ : // for normal queries or `upsertQuery` **inserts** always update the `requestId`
139
+ meta . requestId
140
+ if ( arg . originalArgs !== undefined ) {
141
+ substate . originalArgs = arg . originalArgs
142
+ }
143
+ substate . startedTimeStamp = meta . startedTimeStamp
144
+ } )
145
+ }
146
+
147
+ function writeFulfilledCacheEntry (
148
+ draft : QueryState < any > ,
149
+ meta : {
150
+ arg : QueryThunkArg
151
+ requestId : string
152
+ // requestStatus: 'fulfilled'
153
+ } & {
154
+ fulfilledTimeStamp : number
155
+ baseQueryMeta : unknown
156
+ // RTK_autoBatch: true
157
+ } ,
158
+ payload : unknown ,
159
+ ) {
160
+ updateQuerySubstateIfExists ( draft , meta . arg . queryCacheKey , ( substate ) => {
161
+ if ( substate . requestId !== meta . requestId && ! isUpsertQuery ( meta . arg ) )
162
+ return
163
+ const { merge } = definitions [ meta . arg . endpointName ] as QueryDefinition <
164
+ any ,
165
+ any ,
166
+ any ,
167
+ any
168
+ >
169
+ substate . status = QueryStatus . fulfilled
170
+
171
+ if ( merge ) {
172
+ if ( substate . data !== undefined ) {
173
+ const { fulfilledTimeStamp, arg, baseQueryMeta, requestId } = meta
174
+ // There's existing cache data. Let the user merge it in themselves.
175
+ // We're already inside an Immer-powered reducer, and the user could just mutate `substate.data`
176
+ // themselves inside of `merge()`. But, they might also want to return a new value.
177
+ // Try to let Immer figure that part out, save the result, and assign it to `substate.data`.
178
+ let newData = createNextState ( substate . data , ( draftSubstateData ) => {
179
+ // As usual with Immer, you can mutate _or_ return inside here, but not both
180
+ return merge ( draftSubstateData , payload , {
181
+ arg : arg . originalArgs ,
182
+ baseQueryMeta,
183
+ fulfilledTimeStamp,
184
+ requestId,
185
+ } )
186
+ } )
187
+ substate . data = newData
188
+ } else {
189
+ // Presumably a fresh request. Just cache the response data.
190
+ substate . data = payload
191
+ }
192
+ } else {
193
+ // Assign or safely update the cache data.
194
+ substate . data =
195
+ definitions [ meta . arg . endpointName ] . structuralSharing ?? true
196
+ ? copyWithStructuralSharing (
197
+ isDraft ( substate . data )
198
+ ? original ( substate . data )
199
+ : substate . data ,
200
+ payload ,
201
+ )
202
+ : payload
203
+ }
204
+
205
+ delete substate . error
206
+ substate . fulfilledTimeStamp = meta . fulfilledTimeStamp
207
+ } )
208
+ }
115
209
const querySlice = createSlice ( {
116
210
name : `${ reducerPath } /queries` ,
117
211
initialState : initialState as QueryState < any > ,
@@ -149,83 +243,10 @@ export function buildSlice({
149
243
builder
150
244
. addCase ( queryThunk . pending , ( draft , { meta, meta : { arg } } ) => {
151
245
const upserting = isUpsertQuery ( arg )
152
- draft [ arg . queryCacheKey ] ??= {
153
- status : QueryStatus . uninitialized ,
154
- endpointName : arg . endpointName ,
155
- }
156
-
157
- updateQuerySubstateIfExists ( draft , arg . queryCacheKey , ( substate ) => {
158
- substate . status = QueryStatus . pending
159
-
160
- substate . requestId =
161
- upserting && substate . requestId
162
- ? // for `upsertQuery` **updates**, keep the current `requestId`
163
- substate . requestId
164
- : // for normal queries or `upsertQuery` **inserts** always update the `requestId`
165
- meta . requestId
166
- if ( arg . originalArgs !== undefined ) {
167
- substate . originalArgs = arg . originalArgs
168
- }
169
- substate . startedTimeStamp = meta . startedTimeStamp
170
- } )
246
+ writePendingCacheEntry ( draft , arg , upserting , meta )
171
247
} )
172
248
. addCase ( queryThunk . fulfilled , ( draft , { meta, payload } ) => {
173
- updateQuerySubstateIfExists (
174
- draft ,
175
- meta . arg . queryCacheKey ,
176
- ( substate ) => {
177
- if (
178
- substate . requestId !== meta . requestId &&
179
- ! isUpsertQuery ( meta . arg )
180
- )
181
- return
182
- const { merge } = definitions [
183
- meta . arg . endpointName
184
- ] as QueryDefinition < any , any , any , any >
185
- substate . status = QueryStatus . fulfilled
186
-
187
- if ( merge ) {
188
- if ( substate . data !== undefined ) {
189
- const { fulfilledTimeStamp, arg, baseQueryMeta, requestId } =
190
- meta
191
- // There's existing cache data. Let the user merge it in themselves.
192
- // We're already inside an Immer-powered reducer, and the user could just mutate `substate.data`
193
- // themselves inside of `merge()`. But, they might also want to return a new value.
194
- // Try to let Immer figure that part out, save the result, and assign it to `substate.data`.
195
- let newData = createNextState (
196
- substate . data ,
197
- ( draftSubstateData ) => {
198
- // As usual with Immer, you can mutate _or_ return inside here, but not both
199
- return merge ( draftSubstateData , payload , {
200
- arg : arg . originalArgs ,
201
- baseQueryMeta,
202
- fulfilledTimeStamp,
203
- requestId,
204
- } )
205
- } ,
206
- )
207
- substate . data = newData
208
- } else {
209
- // Presumably a fresh request. Just cache the response data.
210
- substate . data = payload
211
- }
212
- } else {
213
- // Assign or safely update the cache data.
214
- substate . data =
215
- definitions [ meta . arg . endpointName ] . structuralSharing ?? true
216
- ? copyWithStructuralSharing (
217
- isDraft ( substate . data )
218
- ? original ( substate . data )
219
- : substate . data ,
220
- payload ,
221
- )
222
- : payload
223
- }
224
-
225
- delete substate . error
226
- substate . fulfilledTimeStamp = meta . fulfilledTimeStamp
227
- } ,
228
- )
249
+ writeFulfilledCacheEntry ( draft , meta , payload )
229
250
} )
230
251
. addCase (
231
252
queryThunk . rejected ,
0 commit comments