Skip to content

useInfiniteScroll

useInfiniteScroll encapsulates the common infinite scroll logic.

const { data, loading, loadingMore, loadMore } = useInfiniteScroll(service)
const { data, loading, loadingMore, loadMore } = useInfiniteScroll(service)

The first parameter service of useInfiniteScroll is an asynchronous function. The input and output parameters of this function have the following conventions:

  1. The data returned by service must contain a list array, the type is { list: any[], ...rest }
  2. The input parameter of service is the latest merged data

f the data returned for the first request is { list: [1, 2, 3], nextId: 4 }, the data returned for the second time is { list: [4, 5, 6], nextId: 7 } , then we will automatically merge list, and the merged data will be { list: [1, 2, 3, 4, 5, 6], nextId: 7 }.

Basic usage

In the first example, we demonstrate the implementation of a most basic infinite scroll.

Pagination

In the data fixation scenario, we sometimes use page and pageSize to request new data.

Scrolling to automatically load

In the infinite scrolling scenario, the most common case is to automatically load when scrolling to the bottom. By configuring the following properties, you can achieve scrolling to automatically load.

  • options.target specifies the parent element, The parent element needs to set a fixed height and support internal scrolling
  • options.isNoMore determines if there is no more data

Data reset

The data can be reset by reload. The following example shows that after the filter changes, the data is reset to the first page.

The above code can be implemented with reloadDeps syntax sugar. When reloadDeps changes, reload will be triggered automatically.

Data mutation

With mutate, we can directly modify the current data. The following example demonstrates deleting a record from the data.

API

export type Data = { list: any[];[key: string]: any; };
export type Service<TData extends Data> = (currentData?: TData) => Promise<TData>;

const {
  data: Ref<TData>;
  loading: ComputedRef<boolean>;
  loadingMore: Ref<boolean>;
  noMore: ComputedRef<boolean>;
  loadMore: () => void;
  loadMoreAsync: () => Promise<TData>;
  reload: () => void;
  reloadAsync: () => Promise<TData>;
  cancel: () => void;
  mutate: (data?: TData) => void;
} = useInfiniteScroll<TData extends Data>(
  service: (currentData?: TData) => Promise<TData>,
  {
    target?: BasicTarget;
    isNoMore?: (data?: TData) => boolean;
    threshold?: number;
    manual?: boolean;
    reloadDeps?: DependencyList;
    onBefore?: () => void;
    onSuccess?: (data: TData) => void;
    onError?: (e: Error) => void;
    onFinally?: (data?: TData, e?: Error) => void;
  }
);
export type Data = { list: any[];[key: string]: any; };
export type Service<TData extends Data> = (currentData?: TData) => Promise<TData>;

const {
  data: Ref<TData>;
  loading: ComputedRef<boolean>;
  loadingMore: Ref<boolean>;
  noMore: ComputedRef<boolean>;
  loadMore: () => void;
  loadMoreAsync: () => Promise<TData>;
  reload: () => void;
  reloadAsync: () => Promise<TData>;
  cancel: () => void;
  mutate: (data?: TData) => void;
} = useInfiniteScroll<TData extends Data>(
  service: (currentData?: TData) => Promise<TData>,
  {
    target?: BasicTarget;
    isNoMore?: (data?: TData) => boolean;
    threshold?: number;
    manual?: boolean;
    reloadDeps?: DependencyList;
    onBefore?: () => void;
    onSuccess?: (data: TData) => void;
    onError?: (e: Error) => void;
    onFinally?: (data?: TData, e?: Error) => void;
  }
);

Result

PropertyDescriptionType
dataThe data returned by the service, where the list attribute is the aggregated dataReadonly<Ref<TData>> | undefined
loadingIs the first request in progressComputedRef<boolean>
loadingMoreIs more data request in progressReadonly<Ref<boolean>>
noMoreWhether there is no more data, it will take effect after configuring options.isNoMoreComputedRef<boolean>
loadMoreLoad more data, it will automatically catch the exception, and handle it through options.onError() => void
loadMoreAsyncLoad more data, which is consistent with the behavior of loadMore, but returns Promise, so you need to handle the exception yourself() => Promise<TData>
reloadLoad the first page of data, it will automatically catch the exception, and handle it through options.onError() => void
reloadAsyncLoad the first page of data, which is consistent with the behavior of reload, but returns Promise, so you need to handle the exception yourself() => Promise<TData>
mutateModify data directly(data?: TData) => void
cancelIgnore the current Promise response() => void

Options

PropertyDescriptionTypeDefault
targetspecifies the parent element. If it exists, it will trigger the loadMore when scrolling to the bottom. Needs to work with isNoMore to know when there is no more data to load() => Element | Element | MutableRefObject<Element>-
isNoMoredetermines if there is no more data, the input parameter is the latest merged data(data?: TData) => boolean-
thresholdThe pixel threshold to the bottom for the scrolling to loadnumber100
reloadDepsWhen the content of the array changes, reload will be triggeredWatchSource | any[] |any-
manual
  • The default is false. That is, the service is automatically executed during initialization.
  • If set to true, you need to manually call run or runAsync to trigger execution
booleanfalse
onBeforeTriggered before service execution() => void-
onSuccessTriggered when service resolve(data: TData) => void-
onErrorTriggered when service reject(e: Error) => void-
onFinallyTriggered when service execution is complete(data?: TData, e?: Error) => void-

Source

SourceDocsDemo