You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/rtk-query/internal/buildMiddleware/invalidationByTags.mdx
+28-23
Original file line number
Diff line number
Diff line change
@@ -1,10 +1,11 @@
1
1
# invalidationByTags
2
2
3
-
4
3
## Overview
4
+
5
5
`InvalidationByTagsHandler` is a handler instantiated during the (BuildMiddleware) step of the build. The handler acts as a (Middleware) and executes each step in response to matching of internal asyncThunk actions.
6
6
7
7
The matchers used for a "invalidation sequence" are these two cases:
8
+
8
9
```ts no-transpile
9
10
const isThunkActionWithTags =isAnyOf(
10
11
isFulfilled(mutationThunk),
@@ -21,11 +22,12 @@ const isQueryEnd = isAnyOf(
21
22
22
23
The handler has 3 core conditionals that trigger a sequence:
23
24
24
-
*Conditional 1 AND 3 are identical in process except the tags are calculated from the payload rather than from the action and endpointDefinition*
25
+
_Conditional 1 AND 3 are identical in process except the tags are calculated from the payload rather than from the action and endpointDefinition_
25
26
26
27
1. Mutation trigger
27
28
2. Query trigger
28
29
3. Manual invalidation via `api.util.invalidateTags` trigger
1. invalidateTags function is called with a list of tags generated from the action metadata
63
-
2. in the case of a [queryThunk] resolution an empty set of tags is always provided
64
-
2. The tags calculated are added to the list of pending tags to invalidate (see [delayed](Delayed))
64
+
1. invalidateTags function is called with a list of tags generated from the action metadata
65
+
2. in the case of a [queryThunk] resolution an empty set of tags is always provided
66
+
2. The tags calculated are added to the list of pending tags to invalidate (see [delayed](#Delayed))
65
67
3. (optional: 'Delayed') the invalidateTags function is ended if the `apiSlice.invalidationBehaviour` is set to "delayed" and there are any pending thunks/queries running in that `apiSlice`
66
68
4. Pending tags are reset to an empty list, if there are no tags the function ends here
67
69
5. Selects all `{ endpointName, originalArgs, queryCacheKey }` combinations that would be invalidated by a specific set of tags.
68
-
6. Iterates through queryCacheKeys selected and performs one of two actions if the query exists*
69
-
1. removes cached query result - via the `removeQueryResult` action - if no subscription is active
70
-
2. if the query is "uninitialized" it initiates a `refetchQuery` action
70
+
6. Iterates through queryCacheKeys selected and performs one of two actions if the query exists\*
71
+
1. removes cached query result - via the `removeQueryResult` action - if no subscription is active
72
+
2. if the query is "uninitialized" it initiates a `refetchQuery` action
@@ -99,6 +103,7 @@ Step 6 is performed within a `context.batch()` call.
99
103
RTKQ now has internal logic to delay tag invalidation briefly, to allow multiple invalidations to get handled together. This is controlled by a new `invalidationBehavior:'immediate'|'delayed'` flag on `createApi`. The new default behavior is `'delayed'`. Set it to `'immediate'` to revert to the behavior in RTK 1.9.
100
104
101
105
The `'delayed'` behaviour enables a check inside `invalidationByTags` that will cause any invalidation that is triggered while a query/mutation is still pending to batch the invalidation until no query/mutation is running.
// There's existing cache data. Let the user merge it in themselves.
26
29
// We're already inside an Immer-powered reducer, and the user could just mutate `substate.data`
27
30
// themselves inside of `merge()`. But, they might also want to return a new value.
28
31
// Try to let Immer figure that part out, save the result, and assign it to `substate.data`.
29
-
let newData =createNextState(
30
-
substate.data,
31
-
(draftSubstateData) => {
32
-
// As usual with Immer, you can mutate _or_ return inside here, but not both
33
-
returnmerge(draftSubstateData, payload, {
34
-
arg: arg.originalArgs,
35
-
baseQueryMeta,
36
-
fulfilledTimeStamp,
37
-
requestId,
38
-
})
39
-
},
40
-
)
32
+
let newData =createNextState(substate.data, (draftSubstateData) => {
33
+
// As usual with Immer, you can mutate _or_ return inside here, but not both
34
+
returnmerge(draftSubstateData, payload, {
35
+
arg: arg.originalArgs,
36
+
baseQueryMeta,
37
+
fulfilledTimeStamp,
38
+
requestId,
39
+
})
40
+
})
41
41
substate.data=newData
42
42
} else {
43
43
// Presumably a fresh request. Just cache the response data.
@@ -47,85 +47,102 @@ let newData = createNextState(
47
47
```
48
48
49
49
-`queryThunk.rejected`
50
-
- utilises `condition()` from `queryThunk` and does nothing if the rejection is a result of `condition()` (indicates a thunk is already running here)
51
-
- else substate.error is set and the status is changed to rejected
50
+
- utilises `condition()` from `queryThunk` and does nothing if the rejection is a result of `condition()` (indicates a thunk is already running here)
51
+
- else substate.error is set and the status is changed to rejected
52
52
-`hasRehydrationInfo`
53
-
- iterates through and resets entries for all fulfilled or rejected status
53
+
- iterates through and resets entries for all fulfilled or rejected status
54
54
55
55
### mutationSlice
56
+
56
57
#### reducers
58
+
57
59
-`removeMutationResult`
58
-
- calls `getMutationCacheKey` from payload
59
-
- if cacheKey is in draft it deletes `draft[cacheKey`(?)
60
+
- calls `getMutationCacheKey` from payload
61
+
- if cacheKey is in draft it deletes `draft[cacheKey`(?)
62
+
60
63
#### extraReducers - matching mutationThunk cases
64
+
61
65
-`mutationThunk.pending`
62
-
- exits if track is set to false
63
-
- otherwise updates appropriate cacheKey with requestId, pending status and startedTimeStamp
66
+
- exits if track is set to false
67
+
- otherwise updates appropriate cacheKey with requestId, pending status and startedTimeStamp
64
68
-`mutationThunk.fulfilled`
65
-
- exits if track is set to false
66
-
- otherwise sets data off payload and fulfilledTimeStamp
69
+
- exits if track is set to false
70
+
- otherwise sets data off payload and fulfilledTimeStamp
67
71
-`mutationThunk.rejected`
68
-
- exits if track is set to false
69
-
- otherwise sets error and status to rejected
72
+
- exits if track is set to false
73
+
- otherwise sets error and status to rejected
70
74
-`hasRehydrationInfo`
71
-
- iterates through and resets entries for all fulfilled or rejected status
75
+
- iterates through and resets entries for all fulfilled or rejected status
72
76
73
77
### invalidationSlice
74
78
75
79
#### reducers
80
+
76
81
- updateProvidedBy
77
-
- takes queryCacheKey and providedTags from payload
78
-
- appends to a list of idSubscriptions the queryCacheKey that are currently subscribed to for each tag
82
+
- takes queryCacheKey and providedTags from payload
83
+
- appends to a list of idSubscriptions the queryCacheKey that are currently subscribed to for each tag
84
+
79
85
#### extraReducers
86
+
80
87
-`querySlice.actions.removeQueryResult`,
81
-
- deletes relevant queryCacheKey entry from list of subscription ids
88
+
- deletes relevant queryCacheKey entry from list of subscription ids
82
89
-`hasRehydrationInfo`
83
-
- TODO
90
+
- TODO
84
91
-`queryThunk.fulfilled` or `queryThunk.rejected`
85
-
- gets list of tags from action and endpoint definition
86
-
- gets queryCacheKey
87
-
- calls updateProvidedBy action
92
+
- gets list of tags from action and endpoint definition
93
+
- gets queryCacheKey
94
+
- calls updateProvidedBy action
88
95
89
96
### subscriptionSlice / internalSubscriptionSlice
97
+
90
98
#### reducers
99
+
91
100
- updateSubscriptionOptions
92
101
- unsubscribeQueryResult
93
102
- internal_getRTKQSubscriptions
94
103
- subscriptionsUpdated
95
-
- applyPatches() to the state from the payload
104
+
- applyPatches() to the state from the payload
96
105
97
106
### configSlice
107
+
98
108
#### reducers
109
+
99
110
- middlewareRegistered
100
-
- toggles whether the middleware is registered or if there is a conflict
111
+
- toggles whether the middleware is registered or if there is a conflict
112
+
101
113
#### extraReducers
114
+
102
115
-`onOnline`
103
-
- manages state.online in response to listenerMiddleware
116
+
- manages state.online in response to listenerMiddleware
104
117
-`onOffline`
105
-
- manages state.online in response to listenerMiddleware
118
+
- manages state.online in response to listenerMiddleware
106
119
-`onFocus`
107
-
- manages state.focused in response to listenerMiddleware
120
+
- manages state.focused in response to listenerMiddleware
108
121
-`onFocusLost`
109
-
- manages state.focused in response to listenerMiddleware
122
+
- manages state.focused in response to listenerMiddleware
110
123
-`hasRehydrationInfo`
111
-
- lists a comment that says: "update the state to be a new object to be picked up as a "state change" by redux-persist's `autoMergeLevel2`"
112
-
124
+
- lists a comment that says: "update the state to be a new object to be picked up as a "state change" by redux-persist's `autoMergeLevel2`"
113
125
114
126
## Functions
127
+
115
128
### `updateQuerySubstateIfExists`
129
+
116
130
Utility function that takes the api/endpoint state, queryCacheKey and Update function.
117
131
The "SubState" is determined by accessing the `queryCacheKey` value inside the state. If the substate exists, the update function is executed on the substate.
conditionally determines the cachekey to be used for the mutation, prioritising the argument provided, followed by the provided cacheKey, and the generated requestId otherwise
145
+
129
146
```ts no-transpile
130
147
exportfunction getMutationCacheKey(
131
148
id:
@@ -140,12 +157,12 @@ export function getMutationCacheKey(
140
157
### `getMutationSubstateIfExists`
141
158
142
159
same as query version except it uses the id instead of the queryCacheKey, and uses the `getMutationCacheKey` to determine the cachekey
Copy file name to clipboardExpand all lines: docs/rtk-query/internal/overview.mdx
+9-2
Original file line number
Diff line number
Diff line change
@@ -7,9 +7,10 @@
7
7
This documentation is intended to provide a high-level overview of the internal architecture of RTK-Query. It is not intended to be a comprehensive guide to the library, but rather a guide to the internal architecture and how it works.
8
8
9
9
## createApi - The Entry Point
10
+
10
11
When `createApi()` is called it takes the options provided and calls internally the `buildCreateApi()` function passing into it two modules:
11
12
12
-
*Modules are RTK-Query's method of customizing how the `createApi` method handles endpoints.*
13
+
_Modules are RTK-Query's method of customizing how the `createApi` method handles endpoints._
13
14
14
15
-`coreModule()` - responsible for the majority of the internal handling using core redux logic i.e. slices, reducers, asyncThunks.
15
16
-`reactHooksModule()` - a module that generates react hooks from endpoints using react-redux
@@ -19,6 +20,7 @@ When `createApi()` is called it takes the options provided and calls internally
19
20
The core module takes the `api` and the options passed to `createApi()`. In turn an internal set of "build" methods are called. Each of these build methods create a set of functions which are assigned to either `api.util` or `api.internalActions` and/or passed to a future "build" step.
20
21
21
22
### buildThunks
23
+
22
24
RTK-Query's internal functionality operates using the same `asyncThunk` exposed from RTK. In the first "build" method, a number of thunks are generated for the core module to use:
23
25
24
26
-`queryThunk`
@@ -30,10 +32,12 @@ RTK-Query's internal functionality operates using the same `asyncThunk` exposed
30
32
-`buildMatchThunkActions`
31
33
32
34
### buildSlice
35
+
33
36
RTK-Query uses a very familiar redux-centric architecture. Where the `api` is a slice of your store, the `api` has its own slices created within it. These slices are where the majority of the RTKQ magic happens.
34
37
35
38
The slices built inside this "build" are:
36
-
*Some of which have their own actions*
39
+
_Some of which have their own actions_
40
+
37
41
- querySlice
38
42
- mutationSlice
39
43
- invalidationSlice
@@ -44,6 +48,7 @@ The slices built inside this "build" are:
44
48
buildSlice also exposes the core action `resetApiState` which is subsequently added to the `api.util`
45
49
46
50
### buildMiddleware
51
+
47
52
RTK-Query has a series of custom middlewares established within its store to handle additional responses in addition to the core logic established within the slices from buildSlice.
48
53
49
54
Each middleware built during this step is referred to internally as a "Handler" and are as follows:
@@ -56,6 +61,7 @@ Each middleware built during this step is referred to internally as a "Handler"
56
61
- `buildQueryLifecycleHandler
57
62
58
63
### buildSelectors
64
+
59
65
build selectors is a crucial step that exposes to the `api` and utils:
60
66
61
67
- `buildQuerySelector
@@ -64,4 +70,5 @@ build selectors is a crucial step that exposes to the `api` and utils:
64
70
- `selectCachedArgsForQuery
65
71
66
72
### return
73
+
67
74
Finally each endpoint passed into the `createApi()` is iterated over and assigned either the query or the mutation selectors, initiators and match cases.
0 commit comments