Fetch enough pages to fill a page's worth of items (#4863)
* Fetch enough pages to fill a page's worth of items * Add failsafe in case of appview bugzio/stable
parent
70ffd387e3
commit
d2e88cc623
|
@ -59,7 +59,6 @@ export function useNotificationFeedQuery(opts?: {
|
|||
const moderationOpts = useModerationOpts()
|
||||
const unreads = useUnreadNotificationsApi()
|
||||
const enabled = opts?.enabled !== false
|
||||
const lastPageCountRef = useRef(0)
|
||||
const gate = useGate()
|
||||
|
||||
// false: force showing all notifications
|
||||
|
@ -121,28 +120,52 @@ export function useNotificationFeedQuery(opts?: {
|
|||
},
|
||||
})
|
||||
|
||||
// The server may end up returning an empty page, a page with too few items,
|
||||
// or a page with items that end up getting filtered out. When we fetch pages,
|
||||
// we'll keep track of how many items we actually hope to see. If the server
|
||||
// doesn't return enough items, we're going to continue asking for more items.
|
||||
const lastItemCount = useRef(0)
|
||||
const wantedItemCount = useRef(0)
|
||||
const autoPaginationAttemptCount = useRef(0)
|
||||
useEffect(() => {
|
||||
const {isFetching, hasNextPage, data} = query
|
||||
if (isFetching || !hasNextPage) {
|
||||
return
|
||||
}
|
||||
|
||||
// avoid double-fires of fetchNextPage()
|
||||
if (
|
||||
lastPageCountRef.current !== 0 &&
|
||||
lastPageCountRef.current === data?.pages?.length
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
// fetch next page if we haven't gotten a full page of content
|
||||
let count = 0
|
||||
const {data, isLoading, isRefetching, isFetchingNextPage, hasNextPage} =
|
||||
query
|
||||
// Count the items that we already have.
|
||||
let itemCount = 0
|
||||
for (const page of data?.pages || []) {
|
||||
count += page.items.length
|
||||
itemCount += page.items.length
|
||||
}
|
||||
if (count < PAGE_SIZE && (data?.pages.length || 0) < 6) {
|
||||
query.fetchNextPage()
|
||||
lastPageCountRef.current = data?.pages?.length || 0
|
||||
|
||||
// If items got truncated, reset the state we're tracking below.
|
||||
if (itemCount !== lastItemCount.current) {
|
||||
if (itemCount < lastItemCount.current) {
|
||||
wantedItemCount.current = itemCount
|
||||
}
|
||||
lastItemCount.current = itemCount
|
||||
}
|
||||
|
||||
// Now track how many items we really want, and fetch more if needed.
|
||||
if (isLoading || isRefetching) {
|
||||
// During the initial fetch, we want to get an entire page's worth of items.
|
||||
wantedItemCount.current = PAGE_SIZE
|
||||
} else if (isFetchingNextPage) {
|
||||
if (itemCount > wantedItemCount.current) {
|
||||
// We have more items than wantedItemCount, so wantedItemCount must be out of date.
|
||||
// Some other code must have called fetchNextPage(), for example, from onEndReached.
|
||||
// Adjust the wantedItemCount to reflect that we want one more full page of items.
|
||||
wantedItemCount.current = itemCount + PAGE_SIZE
|
||||
}
|
||||
} else if (hasNextPage) {
|
||||
// At this point we're not fetching anymore, so it's time to make a decision.
|
||||
// If we didn't receive enough items from the server, paginate again until we do.
|
||||
if (itemCount < wantedItemCount.current) {
|
||||
autoPaginationAttemptCount.current++
|
||||
if (autoPaginationAttemptCount.current < 50 /* failsafe */) {
|
||||
query.fetchNextPage()
|
||||
}
|
||||
} else {
|
||||
autoPaginationAttemptCount.current = 0
|
||||
}
|
||||
}
|
||||
}, [query])
|
||||
|
||||
|
|
|
@ -134,7 +134,6 @@ export function usePostFeedQuery(
|
|||
args: typeof selectArgs
|
||||
result: InfiniteData<FeedPage>
|
||||
} | null>(null)
|
||||
const lastPageCountRef = useRef(0)
|
||||
const isDiscover = feedDesc.includes(DISCOVER_FEED_URI)
|
||||
|
||||
// Make sure this doesn't invalidate unless really needed.
|
||||
|
@ -376,30 +375,54 @@ export function usePostFeedQuery(
|
|||
),
|
||||
})
|
||||
|
||||
// The server may end up returning an empty page, a page with too few items,
|
||||
// or a page with items that end up getting filtered out. When we fetch pages,
|
||||
// we'll keep track of how many items we actually hope to see. If the server
|
||||
// doesn't return enough items, we're going to continue asking for more items.
|
||||
const lastItemCount = useRef(0)
|
||||
const wantedItemCount = useRef(0)
|
||||
const autoPaginationAttemptCount = useRef(0)
|
||||
useEffect(() => {
|
||||
const {isFetching, hasNextPage, data} = query
|
||||
if (isFetching || !hasNextPage) {
|
||||
return
|
||||
}
|
||||
|
||||
// avoid double-fires of fetchNextPage()
|
||||
if (
|
||||
lastPageCountRef.current !== 0 &&
|
||||
lastPageCountRef.current === data?.pages?.length
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
// fetch next page if we haven't gotten a full page of content
|
||||
let count = 0
|
||||
const {data, isLoading, isRefetching, isFetchingNextPage, hasNextPage} =
|
||||
query
|
||||
// Count the items that we already have.
|
||||
let itemCount = 0
|
||||
for (const page of data?.pages || []) {
|
||||
for (const slice of page.slices) {
|
||||
count += slice.items.length
|
||||
itemCount += slice.items.length
|
||||
}
|
||||
}
|
||||
if (count < PAGE_SIZE && (data?.pages.length || 0) < 6) {
|
||||
query.fetchNextPage()
|
||||
lastPageCountRef.current = data?.pages?.length || 0
|
||||
|
||||
// If items got truncated, reset the state we're tracking below.
|
||||
if (itemCount !== lastItemCount.current) {
|
||||
if (itemCount < lastItemCount.current) {
|
||||
wantedItemCount.current = itemCount
|
||||
}
|
||||
lastItemCount.current = itemCount
|
||||
}
|
||||
|
||||
// Now track how many items we really want, and fetch more if needed.
|
||||
if (isLoading || isRefetching) {
|
||||
// During the initial fetch, we want to get an entire page's worth of items.
|
||||
wantedItemCount.current = PAGE_SIZE
|
||||
} else if (isFetchingNextPage) {
|
||||
if (itemCount > wantedItemCount.current) {
|
||||
// We have more items than wantedItemCount, so wantedItemCount must be out of date.
|
||||
// Some other code must have called fetchNextPage(), for example, from onEndReached.
|
||||
// Adjust the wantedItemCount to reflect that we want one more full page of items.
|
||||
wantedItemCount.current = itemCount + PAGE_SIZE
|
||||
}
|
||||
} else if (hasNextPage) {
|
||||
// At this point we're not fetching anymore, so it's time to make a decision.
|
||||
// If we didn't receive enough items from the server, paginate again until we do.
|
||||
if (itemCount < wantedItemCount.current) {
|
||||
autoPaginationAttemptCount.current++
|
||||
if (autoPaginationAttemptCount.current < 50 /* failsafe */) {
|
||||
query.fetchNextPage()
|
||||
}
|
||||
} else {
|
||||
autoPaginationAttemptCount.current = 0
|
||||
}
|
||||
}
|
||||
}, [query])
|
||||
|
||||
|
|
Loading…
Reference in New Issue