···5959 const moderationOpts = useModerationOpts()
6060 const unreads = useUnreadNotificationsApi()
6161 const enabled = opts?.enabled !== false
6262- const lastPageCountRef = useRef(0)
6362 const gate = useGate()
64636564 // false: force showing all notifications
···121120 },
122121 })
123122123123+ // The server may end up returning an empty page, a page with too few items,
124124+ // or a page with items that end up getting filtered out. When we fetch pages,
125125+ // we'll keep track of how many items we actually hope to see. If the server
126126+ // doesn't return enough items, we're going to continue asking for more items.
127127+ const lastItemCount = useRef(0)
128128+ const wantedItemCount = useRef(0)
129129+ const autoPaginationAttemptCount = useRef(0)
124130 useEffect(() => {
125125- const {isFetching, hasNextPage, data} = query
126126- if (isFetching || !hasNextPage) {
127127- return
131131+ const {data, isLoading, isRefetching, isFetchingNextPage, hasNextPage} =
132132+ query
133133+ // Count the items that we already have.
134134+ let itemCount = 0
135135+ for (const page of data?.pages || []) {
136136+ itemCount += page.items.length
128137 }
129138130130- // avoid double-fires of fetchNextPage()
131131- if (
132132- lastPageCountRef.current !== 0 &&
133133- lastPageCountRef.current === data?.pages?.length
134134- ) {
135135- return
139139+ // If items got truncated, reset the state we're tracking below.
140140+ if (itemCount !== lastItemCount.current) {
141141+ if (itemCount < lastItemCount.current) {
142142+ wantedItemCount.current = itemCount
143143+ }
144144+ lastItemCount.current = itemCount
136145 }
137146138138- // fetch next page if we haven't gotten a full page of content
139139- let count = 0
140140- for (const page of data?.pages || []) {
141141- count += page.items.length
142142- }
143143- if (count < PAGE_SIZE && (data?.pages.length || 0) < 6) {
144144- query.fetchNextPage()
145145- lastPageCountRef.current = data?.pages?.length || 0
147147+ // Now track how many items we really want, and fetch more if needed.
148148+ if (isLoading || isRefetching) {
149149+ // During the initial fetch, we want to get an entire page's worth of items.
150150+ wantedItemCount.current = PAGE_SIZE
151151+ } else if (isFetchingNextPage) {
152152+ if (itemCount > wantedItemCount.current) {
153153+ // We have more items than wantedItemCount, so wantedItemCount must be out of date.
154154+ // Some other code must have called fetchNextPage(), for example, from onEndReached.
155155+ // Adjust the wantedItemCount to reflect that we want one more full page of items.
156156+ wantedItemCount.current = itemCount + PAGE_SIZE
157157+ }
158158+ } else if (hasNextPage) {
159159+ // At this point we're not fetching anymore, so it's time to make a decision.
160160+ // If we didn't receive enough items from the server, paginate again until we do.
161161+ if (itemCount < wantedItemCount.current) {
162162+ autoPaginationAttemptCount.current++
163163+ if (autoPaginationAttemptCount.current < 50 /* failsafe */) {
164164+ query.fetchNextPage()
165165+ }
166166+ } else {
167167+ autoPaginationAttemptCount.current = 0
168168+ }
146169 }
147170 }, [query])
148171
+42-19
src/state/queries/post-feed.ts
···134134 args: typeof selectArgs
135135 result: InfiniteData<FeedPage>
136136 } | null>(null)
137137- const lastPageCountRef = useRef(0)
138137 const isDiscover = feedDesc.includes(DISCOVER_FEED_URI)
139138140139 // Make sure this doesn't invalidate unless really needed.
···376375 ),
377376 })
378377378378+ // The server may end up returning an empty page, a page with too few items,
379379+ // or a page with items that end up getting filtered out. When we fetch pages,
380380+ // we'll keep track of how many items we actually hope to see. If the server
381381+ // doesn't return enough items, we're going to continue asking for more items.
382382+ const lastItemCount = useRef(0)
383383+ const wantedItemCount = useRef(0)
384384+ const autoPaginationAttemptCount = useRef(0)
379385 useEffect(() => {
380380- const {isFetching, hasNextPage, data} = query
381381- if (isFetching || !hasNextPage) {
382382- return
386386+ const {data, isLoading, isRefetching, isFetchingNextPage, hasNextPage} =
387387+ query
388388+ // Count the items that we already have.
389389+ let itemCount = 0
390390+ for (const page of data?.pages || []) {
391391+ for (const slice of page.slices) {
392392+ itemCount += slice.items.length
393393+ }
383394 }
384395385385- // avoid double-fires of fetchNextPage()
386386- if (
387387- lastPageCountRef.current !== 0 &&
388388- lastPageCountRef.current === data?.pages?.length
389389- ) {
390390- return
396396+ // If items got truncated, reset the state we're tracking below.
397397+ if (itemCount !== lastItemCount.current) {
398398+ if (itemCount < lastItemCount.current) {
399399+ wantedItemCount.current = itemCount
400400+ }
401401+ lastItemCount.current = itemCount
391402 }
392403393393- // fetch next page if we haven't gotten a full page of content
394394- let count = 0
395395- for (const page of data?.pages || []) {
396396- for (const slice of page.slices) {
397397- count += slice.items.length
404404+ // Now track how many items we really want, and fetch more if needed.
405405+ if (isLoading || isRefetching) {
406406+ // During the initial fetch, we want to get an entire page's worth of items.
407407+ wantedItemCount.current = PAGE_SIZE
408408+ } else if (isFetchingNextPage) {
409409+ if (itemCount > wantedItemCount.current) {
410410+ // We have more items than wantedItemCount, so wantedItemCount must be out of date.
411411+ // Some other code must have called fetchNextPage(), for example, from onEndReached.
412412+ // Adjust the wantedItemCount to reflect that we want one more full page of items.
413413+ wantedItemCount.current = itemCount + PAGE_SIZE
398414 }
399399- }
400400- if (count < PAGE_SIZE && (data?.pages.length || 0) < 6) {
401401- query.fetchNextPage()
402402- lastPageCountRef.current = data?.pages?.length || 0
415415+ } else if (hasNextPage) {
416416+ // At this point we're not fetching anymore, so it's time to make a decision.
417417+ // If we didn't receive enough items from the server, paginate again until we do.
418418+ if (itemCount < wantedItemCount.current) {
419419+ autoPaginationAttemptCount.current++
420420+ if (autoPaginationAttemptCount.current < 50 /* failsafe */) {
421421+ query.fetchNextPage()
422422+ }
423423+ } else {
424424+ autoPaginationAttemptCount.current = 0
425425+ }
403426 }
404427 }, [query])
405428