Skip to content

Commit d8190e3

Browse files
authored
Only run transformResponse when a query is used (#5049)
1 parent dce871c commit d8190e3

File tree

2 files changed

+108
-60
lines changed

2 files changed

+108
-60
lines changed

packages/toolkit/src/query/core/buildThunks.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,10 +510,7 @@ export function buildThunks<
510510
endpointDefinition
511511

512512
try {
513-
let transformResponse = getTransformCallbackForEndpoint(
514-
endpointDefinition,
515-
'transformResponse',
516-
)
513+
let transformResponse: TransformCallback = defaultTransformResponse
517514

518515
const baseQueryApi = {
519516
signal,
@@ -587,6 +584,13 @@ export function buildThunks<
587584
// upsertQueryData relies on this to pass in the user-provided value
588585
result = forceQueryFn()
589586
} else if (endpointDefinition.query) {
587+
// We should only run `transformResponse` when the endpoint has a `query` method,
588+
// and we're not doing an `upsertQueryData`.
589+
transformResponse = getTransformCallbackForEndpoint(
590+
endpointDefinition,
591+
'transformResponse',
592+
)
593+
590594
result = await baseQuery(
591595
endpointDefinition.query(finalQueryArg as any),
592596
baseQueryApi,

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

Lines changed: 100 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -4,71 +4,115 @@ import { renderHook, waitFor } from '@testing-library/react'
44
import { actionsReducer, withProvider } from '../../tests/utils/helpers'
55
import type { BaseQueryApi } from '../baseQueryTypes'
66

7-
test('handles a non-async baseQuery without error', async () => {
8-
const baseQuery = (args?: any) => ({ data: args })
9-
const api = createApi({
10-
baseQuery,
11-
endpoints: (build) => ({
12-
getUser: build.query<unknown, number>({
13-
query(id) {
14-
return { url: `user/${id}` }
15-
},
7+
describe('baseline thunk behavior', () => {
8+
test('handles a non-async baseQuery without error', async () => {
9+
const baseQuery = (args?: any) => ({ data: args })
10+
const api = createApi({
11+
baseQuery,
12+
endpoints: (build) => ({
13+
getUser: build.query<unknown, number>({
14+
query(id) {
15+
return { url: `user/${id}` }
16+
},
17+
}),
1618
}),
17-
}),
18-
})
19-
const { getUser } = api.endpoints
20-
const store = configureStore({
21-
reducer: {
22-
[api.reducerPath]: api.reducer,
23-
},
24-
middleware: (gDM) => gDM().concat(api.middleware),
25-
})
26-
27-
const promise = store.dispatch(getUser.initiate(1))
28-
const { data } = await promise
19+
})
20+
const { getUser } = api.endpoints
21+
const store = configureStore({
22+
reducer: {
23+
[api.reducerPath]: api.reducer,
24+
},
25+
middleware: (gDM) => gDM().concat(api.middleware),
26+
})
2927

30-
expect(data).toEqual({
31-
url: 'user/1',
32-
})
28+
const promise = store.dispatch(getUser.initiate(1))
29+
const { data } = await promise
3330

34-
const storeResult = getUser.select(1)(store.getState())
35-
expect(storeResult).toEqual({
36-
data: {
31+
expect(data).toEqual({
3732
url: 'user/1',
38-
},
39-
endpointName: 'getUser',
40-
isError: false,
41-
isLoading: false,
42-
isSuccess: true,
43-
isUninitialized: false,
44-
originalArgs: 1,
45-
requestId: expect.any(String),
46-
status: 'fulfilled',
47-
startedTimeStamp: expect.any(Number),
48-
fulfilledTimeStamp: expect.any(Number),
33+
})
34+
35+
const storeResult = getUser.select(1)(store.getState())
36+
expect(storeResult).toEqual({
37+
data: {
38+
url: 'user/1',
39+
},
40+
endpointName: 'getUser',
41+
isError: false,
42+
isLoading: false,
43+
isSuccess: true,
44+
isUninitialized: false,
45+
originalArgs: 1,
46+
requestId: expect.any(String),
47+
status: 'fulfilled',
48+
startedTimeStamp: expect.any(Number),
49+
fulfilledTimeStamp: expect.any(Number),
50+
})
4951
})
50-
})
5152

52-
test('passes the extraArgument property to the baseQueryApi', async () => {
53-
const baseQuery = (_args: any, api: BaseQueryApi) => ({ data: api.extra })
54-
const api = createApi({
55-
baseQuery,
56-
endpoints: (build) => ({
57-
getUser: build.query<unknown, void>({
58-
query: () => '',
53+
test('passes the extraArgument property to the baseQueryApi', async () => {
54+
const baseQuery = (_args: any, api: BaseQueryApi) => ({ data: api.extra })
55+
const api = createApi({
56+
baseQuery,
57+
endpoints: (build) => ({
58+
getUser: build.query<unknown, void>({
59+
query: () => '',
60+
}),
5961
}),
60-
}),
62+
})
63+
const store = configureStore({
64+
reducer: {
65+
[api.reducerPath]: api.reducer,
66+
},
67+
middleware: (gDM) =>
68+
gDM({ thunk: { extraArgument: 'cakes' } }).concat(api.middleware),
69+
})
70+
const { getUser } = api.endpoints
71+
const { data } = await store.dispatch(getUser.initiate())
72+
expect(data).toBe('cakes')
6173
})
62-
const store = configureStore({
63-
reducer: {
64-
[api.reducerPath]: api.reducer,
65-
},
66-
middleware: (gDM) =>
67-
gDM({ thunk: { extraArgument: 'cakes' } }).concat(api.middleware),
74+
75+
test('only triggers transformResponse when a query method is actually used', async () => {
76+
const baseQuery = (args?: any) => ({ data: args })
77+
const transformResponse = vi.fn((response: any) => response)
78+
const api = createApi({
79+
baseQuery,
80+
endpoints: (build) => ({
81+
hasQuery: build.query<string, string>({
82+
query: (arg) => 'test',
83+
transformResponse,
84+
}),
85+
hasQueryFn: build.query<string, void>(
86+
// @ts-expect-error
87+
{
88+
queryFn: () => ({ data: 'test' }),
89+
transformResponse,
90+
},
91+
),
92+
}),
93+
})
94+
95+
const store = configureStore({
96+
reducer: {
97+
[api.reducerPath]: api.reducer,
98+
},
99+
middleware: (gDM) =>
100+
gDM({ thunk: { extraArgument: 'cakes' } }).concat(api.middleware),
101+
})
102+
103+
await store.dispatch(api.util.upsertQueryData('hasQuery', 'a', 'test'))
104+
expect(transformResponse).not.toHaveBeenCalled()
105+
106+
transformResponse.mockReset()
107+
108+
await store.dispatch(api.endpoints.hasQuery.initiate('b'))
109+
expect(transformResponse).toHaveBeenCalledTimes(1)
110+
111+
transformResponse.mockReset()
112+
113+
await store.dispatch(api.endpoints.hasQueryFn.initiate())
114+
expect(transformResponse).not.toHaveBeenCalled()
68115
})
69-
const { getUser } = api.endpoints
70-
const { data } = await store.dispatch(getUser.initiate())
71-
expect(data).toBe('cakes')
72116
})
73117

74118
describe('re-triggering behavior on arg change', () => {

0 commit comments

Comments
 (0)