Skip to content

Commit 7178061

Browse files
committed
added invalidationByTags.mdx to test sidebar layout
1 parent 9d390b9 commit 7178061

File tree

2 files changed

+133
-0
lines changed

2 files changed

+133
-0
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# invalidationByTags
2+
3+
4+
## Overview
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+
7+
i.e. the primary trigger for a "invalidation sequence" are these two cases:
8+
```ts no-transpile
9+
const isThunkActionWithTags = isAnyOf(
10+
isFulfilled(mutationThunk),
11+
isRejectedWithValue(mutationThunk),
12+
)
13+
14+
const isQueryEnd = isAnyOf(
15+
isFulfilled(mutationThunk, queryThunk),
16+
isRejected(mutationThunk, queryThunk),
17+
)
18+
```
19+
20+
## Triggers
21+
22+
The handler has 3 core conditionals that trigger a sequence:
23+
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+
26+
1. Mutation trigger
27+
2. Query trigger
28+
3. manual invalidation via `api.util.invalidateTags` Sequence
29+
```ts no-transpile
30+
const handler: ApiMiddlewareInternalHandler = (action, mwApi) => {
31+
if (isThunkActionWithTags(action)) {
32+
invalidateTags(
33+
calculateProvidedByThunk(
34+
action,
35+
'invalidatesTags',
36+
endpointDefinitions,
37+
assertTagType,
38+
),
39+
mwApi,
40+
)
41+
} else if (isQueryEnd(action)) {
42+
invalidateTags([], mwApi)
43+
} else if (api.util.invalidateTags.match(action)) {
44+
invalidateTags(
45+
calculateProvidedBy(
46+
action.payload,
47+
undefined,
48+
undefined,
49+
undefined,
50+
undefined,
51+
assertTagType,
52+
),
53+
mwApi,
54+
)
55+
}
56+
}
57+
```
58+
59+
60+
## Core Sequence
61+
1. `invalidateTags()` initiates:
62+
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) )
65+
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+
4. pending tags are reset to an empty list, if there are no tags the function ends here
67+
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
71+
```js no-transpile
72+
const toInvalidate = api.util.selectInvalidatedBy(rootState, tags);
73+
context.batch(() => {
74+
const valuesArray = Array.from(toInvalidate.values());
75+
for (const {
76+
queryCacheKey
77+
} of valuesArray) {
78+
const querySubState = state.queries[queryCacheKey];
79+
const subscriptionSubState = internalState.currentSubscriptions[queryCacheKey] ?? {};
80+
if (querySubState) {
81+
if (countObjectKeys(subscriptionSubState) === 0) {
82+
mwApi.dispatch(removeQueryResult({
83+
queryCacheKey
84+
}));
85+
} else if (querySubState.status !== "uninitialized" /* uninitialized */) {
86+
mwApi.dispatch(refetchQuery(querySubState, queryCacheKey));
87+
}
88+
}
89+
}
90+
});
91+
```
92+
93+
:::note
94+
Step 6 is performed within a `context.batch()` call.
95+
:::
96+
97+
### Delayed
98+
99+
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+
101+
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.
102+
```ts no-transpile
103+
function invalidateTags(
104+
newTags: readonly FullTagDescription<string>[],
105+
mwApi: SubMiddlewareApi,
106+
) {
107+
const rootState = mwApi.getState()
108+
const state = rootState[reducerPath]
109+
110+
pendingTagInvalidations.push(...newTags)
111+
112+
if (
113+
state.config.invalidationBehavior === 'delayed' &&
114+
hasPendingRequests(state)
115+
) {
116+
return
117+
}
118+
```

website/sidebars.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,21 @@
143143
]
144144
}
145145
]
146+
},
147+
{
148+
"type": "category",
149+
"label": "Internal Docs",
150+
"collapsed": true,
151+
"items": [
152+
{
153+
"type": "category",
154+
"label": "Middleware",
155+
"collapsed": true,
156+
"items": [
157+
"rtk-query/internal/buildMiddleware/invalidationByTags"
158+
]
159+
}
160+
]
146161
}
147162
]
148163
}

0 commit comments

Comments
 (0)