1
1
import type { QueryThunk , RejectedAction } from '../buildThunks'
2
2
import type { InternalHandlerBuilder } from './types'
3
- import type { SubscriptionState } from '../apiState'
3
+ import type {
4
+ SubscriptionState ,
5
+ QuerySubstateIdentifier ,
6
+ Subscribers ,
7
+ } from '../apiState'
4
8
import { produceWithPatches } from 'immer'
9
+ import { createSlice , PayloadAction , AnyAction } from '@reduxjs/toolkit'
5
10
6
11
// Copied from https://github.com/feross/queue-microtask
7
12
let promise : Promise < any >
@@ -18,16 +23,71 @@ const queueMicrotaskShim =
18
23
19
24
export const buildBatchedActionsHandler : InternalHandlerBuilder <
20
25
[ actionShouldContinue : boolean , subscriptionExists : boolean ]
21
- > = ( { api, queryThunk } ) => {
22
- const { actuallyMutateSubscriptions } = api . internalActions
26
+ > = ( { api, queryThunk, internalState } ) => {
23
27
const subscriptionsPrefix = `${ api . reducerPath } /subscriptions`
24
28
25
29
let previousSubscriptions : SubscriptionState =
26
30
null as unknown as SubscriptionState
27
31
28
32
let dispatchQueued = false
29
33
30
- return ( action , mwApi , internalState ) => {
34
+ const { updateSubscriptionOptions, unsubscribeQueryResult } =
35
+ api . internalActions
36
+
37
+ // Actually intentionally mutate the subscriptions state used in the middleware
38
+ // This is done to speed up perf when loading many components
39
+ const actuallyMutateSubscriptions = (
40
+ mutableState : SubscriptionState ,
41
+ action : AnyAction
42
+ ) => {
43
+ if ( updateSubscriptionOptions . match ( action ) ) {
44
+ const { queryCacheKey, requestId, options } = action . payload
45
+
46
+ if ( mutableState ?. [ queryCacheKey ] ?. [ requestId ] ) {
47
+ mutableState [ queryCacheKey ] ! [ requestId ] = options
48
+ }
49
+ return true
50
+ }
51
+ if ( unsubscribeQueryResult . match ( action ) ) {
52
+ const { queryCacheKey, requestId } = action . payload
53
+ if ( mutableState [ queryCacheKey ] ) {
54
+ delete mutableState [ queryCacheKey ] ! [ requestId ]
55
+ }
56
+ return true
57
+ }
58
+ if ( api . internalActions . removeQueryResult . match ( action ) ) {
59
+ delete mutableState [ action . payload . queryCacheKey ]
60
+ return true
61
+ }
62
+ if ( queryThunk . pending . match ( action ) ) {
63
+ const {
64
+ meta : { arg, requestId } ,
65
+ } = action
66
+ if ( arg . subscribe ) {
67
+ const substate = ( mutableState [ arg . queryCacheKey ] ??= { } )
68
+ substate [ requestId ] =
69
+ arg . subscriptionOptions ?? substate [ requestId ] ?? { }
70
+
71
+ return true
72
+ }
73
+ }
74
+ if ( queryThunk . rejected . match ( action ) ) {
75
+ const {
76
+ meta : { condition, arg, requestId } ,
77
+ } = action
78
+ if ( condition && arg . subscribe ) {
79
+ const substate = ( mutableState [ arg . queryCacheKey ] ??= { } )
80
+ substate [ requestId ] =
81
+ arg . subscriptionOptions ?? substate [ requestId ] ?? { }
82
+
83
+ return true
84
+ }
85
+ }
86
+
87
+ return false
88
+ }
89
+
90
+ return ( action , mwApi ) => {
31
91
if ( ! previousSubscriptions ) {
32
92
// Initialize it the first time this handler runs
33
93
previousSubscriptions = JSON . parse (
0 commit comments