Skip to content

Commit dbd3b61

Browse files
committed
fix: use correct query and options when creating infinite query result
1 parent 131eb29 commit dbd3b61

File tree

2 files changed

+140
-3
lines changed

2 files changed

+140
-3
lines changed

src/core/infiniteQueryObserver.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,14 +108,14 @@ export class InfiniteQueryObserver<
108108
TQueryData
109109
>
110110
): InfiniteQueryObserverResult<TData, TError> {
111-
const { state } = this.getCurrentQuery()
111+
const { state } = query
112112
const result = super.createResult(query, options)
113113
return {
114114
...result,
115115
fetchNextPage: this.fetchNextPage,
116116
fetchPreviousPage: this.fetchPreviousPage,
117-
hasNextPage: hasNextPage(this.options, state.data?.pages),
118-
hasPreviousPage: hasPreviousPage(this.options, state.data?.pages),
117+
hasNextPage: hasNextPage(options, state.data?.pages),
118+
hasPreviousPage: hasPreviousPage(options, state.data?.pages),
119119
isFetchingNextPage:
120120
state.isFetching && state.fetchMeta?.fetchMore?.direction === 'forward',
121121
isFetchingPreviousPage:

src/react/tests/useInfiniteQuery.test.tsx

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,6 +1144,143 @@ describe('useInfiniteQuery', () => {
11441144
})
11451145
})
11461146

1147+
it('should render correct states even in case of concurrent renders with different properties', async () => {
1148+
const key = queryKey()
1149+
const states: UseInfiniteQueryResult<number>[] = []
1150+
let concurrent = false
1151+
const originalUseEffect = React.useEffect
1152+
const dummyUseEffect = (...args: any[]) => {
1153+
originalUseEffect(() => {
1154+
return
1155+
}, args[1])
1156+
}
1157+
1158+
function Page() {
1159+
const [count, setCount] = React.useState(0)
1160+
1161+
if (concurrent) {
1162+
React.useEffect = dummyUseEffect
1163+
}
1164+
1165+
const state = useInfiniteQuery(
1166+
[key, count],
1167+
async () => {
1168+
await sleep(10)
1169+
return count
1170+
},
1171+
{
1172+
staleTime: Infinity,
1173+
keepPreviousData: true,
1174+
getNextPageParam: () => (count === 0 ? undefined : count + 1),
1175+
}
1176+
)
1177+
1178+
if (concurrent) {
1179+
React.useEffect = originalUseEffect
1180+
}
1181+
1182+
states.push(state)
1183+
1184+
React.useEffect(() => {
1185+
setActTimeout(() => {
1186+
setCount(1)
1187+
}, 20)
1188+
1189+
// Try to simulate concurrent render which does not trigger effects
1190+
setActTimeout(() => {
1191+
concurrent = true
1192+
setCount(0)
1193+
}, 40)
1194+
1195+
setActTimeout(() => {
1196+
concurrent = false
1197+
setCount(2)
1198+
}, 60)
1199+
}, [])
1200+
1201+
return null
1202+
}
1203+
1204+
renderWithClient(queryClient, <Page />)
1205+
1206+
await sleep(100)
1207+
1208+
expect(states.length).toBe(9)
1209+
1210+
// Load query 0
1211+
expect(states[0]).toMatchObject({
1212+
status: 'loading',
1213+
data: undefined,
1214+
isFetching: true,
1215+
isPreviousData: false,
1216+
hasNextPage: undefined,
1217+
})
1218+
// Fetch done
1219+
expect(states[1]).toMatchObject({
1220+
status: 'success',
1221+
data: { pageParams: [undefined], pages: [0] },
1222+
isFetching: false,
1223+
isPreviousData: false,
1224+
hasNextPage: false,
1225+
})
1226+
// Set state to query 1
1227+
expect(states[2]).toMatchObject({
1228+
status: 'success',
1229+
data: { pageParams: [undefined], pages: [0] },
1230+
isFetching: true,
1231+
isPreviousData: true,
1232+
hasNextPage: undefined,
1233+
})
1234+
// Fetch start
1235+
expect(states[3]).toMatchObject({
1236+
status: 'success',
1237+
data: { pageParams: [undefined], pages: [0] },
1238+
isFetching: true,
1239+
isPreviousData: true,
1240+
hasNextPage: undefined,
1241+
})
1242+
// Fetch done
1243+
expect(states[4]).toMatchObject({
1244+
status: 'success',
1245+
data: { pageParams: [undefined], pages: [1] },
1246+
isFetching: false,
1247+
isPreviousData: false,
1248+
hasNextPage: true,
1249+
})
1250+
// Concurrent render for query 0
1251+
expect(states[5]).toMatchObject({
1252+
status: 'success',
1253+
data: { pageParams: [undefined], pages: [0] },
1254+
isFetching: false,
1255+
isPreviousData: false,
1256+
hasNextPage: false,
1257+
})
1258+
// Set state to query 2 (should have query 1 has previous data)
1259+
expect(states[6]).toMatchObject({
1260+
status: 'success',
1261+
data: { pageParams: [undefined], pages: [1] },
1262+
isFetching: true,
1263+
isPreviousData: true,
1264+
hasNextPage: undefined,
1265+
})
1266+
// Fetch start
1267+
expect(states[7]).toMatchObject({
1268+
status: 'success',
1269+
data: { pageParams: [undefined], pages: [1] },
1270+
isFetching: true,
1271+
isPreviousData: true,
1272+
hasNextPage: undefined,
1273+
})
1274+
// Fetch done
1275+
expect(states[8]).toMatchObject({
1276+
status: 'success',
1277+
data: { pageParams: [undefined], pages: [2] },
1278+
isFetching: false,
1279+
isPreviousData: false,
1280+
hasNextPage: true,
1281+
})
1282+
})
1283+
11471284
it('should build fresh cursors on refetch', async () => {
11481285
const key = queryKey()
11491286

0 commit comments

Comments
 (0)