Skip to content

Commit a9def39

Browse files
committed
Support null or undefined when invalidateTags is a function
1 parent 459e4ec commit a9def39

File tree

2 files changed

+32
-4
lines changed

2 files changed

+32
-4
lines changed

packages/toolkit/src/query/endpointDefinitions.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import type {
2929
OmitFromUnion,
3030
UnwrapPromise,
3131
} from './tsHelpers'
32+
import { isNotNullish } from './utils'
3233

3334
const resultType = /* @__PURE__ */ Symbol()
3435
const baseQuery = /* @__PURE__ */ Symbol()
@@ -224,7 +225,7 @@ export type GetResultDescriptionFn<
224225
error: ErrorType | undefined,
225226
arg: QueryArg,
226227
meta: MetaType,
227-
) => ReadonlyArray<TagDescription<TagTypes>>
228+
) => ReadonlyArray<TagDescription<TagTypes> | undefined | null>
228229

229230
export type FullTagDescription<TagType> = {
230231
type: TagType
@@ -778,6 +779,7 @@ export function calculateProvidedBy<ResultType, QueryArg, ErrorType, MetaType>(
778779
queryArg,
779780
meta as MetaType,
780781
)
782+
.filter(isNotNullish)
781783
.map(expandTagDescription)
782784
.map(assertTagTypes)
783785
}

packages/toolkit/src/query/tests/buildMiddleware.test.tsx

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,15 @@ const api = createApi({
2525
},
2626
providesTags: ['Bread'],
2727
}),
28+
invalidateFruit: build.mutation({
29+
query: (fruit?: 'Banana' | 'Bread' | null) => ({ url: `invalidate/fruit/${fruit || ''}` }),
30+
invalidatesTags(result, error, arg) {
31+
return [arg]
32+
}
33+
})
2834
}),
2935
})
30-
const { getBanana, getBread } = api.endpoints
36+
const { getBanana, getBread, invalidateFruit } = api.endpoints
3137

3238
const storeRef = setupApiStore(api, {
3339
...actionsReducer,
@@ -91,7 +97,10 @@ it('invalidates tags correctly when null or undefined are provided as tags', asy
9197
})
9298

9399

94-
it.each([{ tags: [undefined, null, 'Bread'] as Parameters<typeof api.util.invalidateTags>['0'] }, { tags: [undefined, null], }, { tags: [] }])('does not invalidate with tags=$tags if no query matches', async ({ tags }) => {
100+
it.each([
101+
{ tags: [undefined, null, 'Bread'] as Parameters<typeof api.util.invalidateTags>['0'] },
102+
{ tags: [undefined, null], }, { tags: [] }]
103+
)('does not invalidate with tags=$tags if no query matches', async ({ tags }) => {
95104
await storeRef.store.dispatch(getBanana.initiate(1))
96105
await storeRef.store.dispatch(api.util.invalidateTags(tags))
97106

@@ -107,4 +116,21 @@ it.each([{ tags: [undefined, null, 'Bread'] as Parameters<typeof api.util.invali
107116

108117
expect(storeRef.store.getState().actions).toMatchSequence(...apiActions)
109118
})
110-
119+
120+
it.each([{ mutationArg: 'Bread' as "Bread" | null | undefined }, { mutationArg: undefined }, { mutationArg: null }])('does not invalidate queries when a mutation with tags=[$mutationArg] runs and does not match anything', async ({ mutationArg }) => {
121+
await storeRef.store.dispatch(getBanana.initiate(1))
122+
await storeRef.store.dispatch(invalidateFruit.initiate(mutationArg))
123+
124+
// Slight pause to let the middleware run and such
125+
await delay(20)
126+
127+
const apiActions = [
128+
api.internalActions.middlewareRegistered.match,
129+
getBanana.matchPending,
130+
getBanana.matchFulfilled,
131+
invalidateFruit.matchPending,
132+
invalidateFruit.matchFulfilled,
133+
]
134+
135+
expect(storeRef.store.getState().actions).toMatchSequence(...apiActions)
136+
})

0 commit comments

Comments
 (0)