@@ -112,6 +112,100 @@ export function buildSlice({
112112 >
113113} ) {
114114 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+ }
115209 const querySlice = createSlice ( {
116210 name : `${ reducerPath } /queries` ,
117211 initialState : initialState as QueryState < any > ,
@@ -149,83 +243,10 @@ export function buildSlice({
149243 builder
150244 . addCase ( queryThunk . pending , ( draft , { meta, meta : { arg } } ) => {
151245 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 )
171247 } )
172248 . 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 )
229250 } )
230251 . addCase (
231252 queryThunk . rejected ,
0 commit comments