Infinite Scroll using an intersection observer? #2122
Unanswered
gmcamposano
asked this question in
Q&A
Replies: 1 comment
-
That's how I approached this issue (using
import { useState, useEffect } from 'react';
import type { ClientError } from 'graphql-request/dist/types';
export type UsePaginationLoadingStateReturn = {
isLoading: boolean;
handleLoadEvent: () => void;
};
type UsePaginationLoadingState = (
swrHookRes: {
data?: Array<unknown | undefined> | undefined;
error?: ClientError;
size: number;
setSize: (callback: (size: number) => number) => void;
},
hasNextPage: boolean,
) => UsePaginationLoadingStateReturn;
const usePaginationLoadingState: UsePaginationLoadingState = (
{ data, setSize, size, error },
hasNextPage,
) => {
const isLoading =
(!data && !error) || // initial load.
(size > 0 && data && typeof data[size - 1] === 'undefined') || // next page load triggered.
false; // ready otherwise.
const [shouldTriggerLoading, setShouldTriggerLoading] = useState(false);
useEffect(() => {
if (!hasNextPage || isLoading || !shouldTriggerLoading) return;
void setSize((size) => size + 1);
setShouldTriggerLoading(false);
}, [shouldTriggerLoading, isLoading, setSize, hasNextPage]);
return { isLoading, handleLoadEvent: () => setShouldTriggerLoading(true) };
};
import { InView } from 'react-intersection-observer';
export type LoadMoreProps = {
/** Disables button until loading state changes. */
isLoading?: boolean;
/** Hides button, if no more data is available. */
hasMoreData: boolean;
/** Action callback - triggered on click and on scroll event. */
handleLoadEvent: () => void;
};
// Regular button which handles onClick event.
export const LoadMore: FC<LoadMoreProps> = ({
isLoading,
hasMoreData,
handleLoadEvent,
}) =>
hasMoreData ? ( // hides button if on last page
<div>
<Button
type="button"
onClick={handleLoadEvent}
active
disabled={isLoading ?? false}>
{loading ? 'Loading...' : 'Load More'}
</Button>
</div>
) : null;
type LoadMoreInfProps = LoadMoreProps & {
/** Offset for scroll event - counted from current viewport down. */
triggerMargin?: number;
};
// Same Button from above, wrapped in InView.
export const LoadMoreInf: FC<LoadMoreInfProps> = ({
hasMoreData,
handleLoadEvent,
isLoading,
triggerMargin = 1500,
}) =>
hasMoreData ? (
<InView
rootMargin={`0px 0px ${triggerMargin}px`}
onChange={(inView) => inView && handleLoadEvent()}>
<LoadMore hasMoreData handleLoadEvent={handleLoadEvent} isLoading ={isLoading} />
</InView>
) : null;
|
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
I have been looking around for examples using the infinite scroll using an intersection observer, but I cant seem to find find one. Can anyone please share an example?
Beta Was this translation helpful? Give feedback.
All reactions