svelte-infinite-loading

repository·main·Indexed 43 days ago

https://github.com/jonasgeiler/svelte-infinite-loading

A mobile-friendly infinite scroll component for Svelte applications (v2.0.0). It supports top and bottom loading directions, built-in spinners, and customizable UI snippets for loading, error, and empty states. The component uses a StateChanger object via the onInfinite event to manage data fetching states including loaded(), complete(), error(), and reset().

Tokens
3.3K
Snippets
10
Records
11
Agent score
54%

What's inside svelte-infinite-loading

  1. How the StateChanger works

    main

    The stateChanger object is passed to your onInfinite function. You must call one of its methods to inform the component of the loading result:

    • stateChanger.loaded(): Marks a successful load and continues listening for the next trigger.
    • stateChanger.complete(): Ends the infinite loading process. It will display the noResults snippet if no items were ever loaded, or the noMore snippet if items were previously loaded.
    • stateChanger.error(): Signals a failure and displays the error snippet.
    • stateChanger.reset(): Resets the component state (functionally equivalent to changing the identifier prop).
    // Example of using stateChanger methods
    async function loadMore(stateChanger: StateChanger) {
      const data = await fetchData();
      if (data.length === 0) {
        stateChanger.complete(); // Shows 'noMore' or 'noResults'
      } else {
        stateChanger.loaded();   // Continues scrolling
      }
    }
  2. Basic Usage of InfiniteLoading

    main

    To implement infinite scrolling, import InfiniteLoading and provide an onInfinite handler. The handler receives a stateChanger object used to communicate the status of the data fetch (success, error, or completion) back to the component.

    <script lang="ts">
    	import InfiniteLoading, { type StateChanger } from 'svelte-infinite-loading';
    
    	type Post = { id: number; title: string };
    
    	let page = 0;
    	const pageSize = 20;
    	let items: Post[] = $state([]);
    
    	async function loadMore(stateChanger: StateChanger) {
    		try {
    			const res = await fetch(`/api/posts?page=${page}&limit=${pageSize}`);
    			const data = (await res.json()) as Post[];
    
    			if (data.length === 0) {
    				stateChanger.complete();
    				return;
    			}
    
    			items = [...items, ...data];
    			page += 1;
    			stateChanger.loaded();
    		} catch {
    			stateChanger.error();
    		}
    	}
    </script>
    
    <ul>
    	{#each items as item (item.id)}
    		<li>{item.title}</li>
    	{/each}
    </ul >
    
    <InfiniteLoading onInfinite={loadMore} />
  3. InfiniteLoading Snippets Reference

    main

    Use Svelte snippets to customize the UI for different loading states:

    | Snippet | Signature | Default behavior |
    | ----------- | ----------- | ---------------------------------------------------------------------- |
    | `noResults` | `Snippet` | Shown when `complete()` is called before any `loaded()`. |
    | `noMore` | `Snippet` | Shown when `complete()` is called after at least one `loaded()`. |
    | `error` | `Snippet<[() => void]>` | Shown when `error()` is called. Receives `attemptLoad` retry callback. |
    | `spinner` | `Snippet<[boolean]>` | Shown while loading. Receives `isFirstLoad` flag. |
  4. InfiniteLoading Props Reference

    main

    Configure the behavior of the infinite scroll component using the following props:

    | Prop | Type | Default | Description |
    | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `distance` | `number` | `100` | Triggers `onInfinite` when the remaining scroll distance reaches this threshold (top or bottom depending on `direction`). |
    | `spinnerType` | `'default' \| 'bubbles' \| 'circles' \| 'spiral' \| 'wavedots'` | `'default'` | Selects a built-in spinner. You can also override with the `spinner` snippet. |
    | `direction` | `'top' \| 'bottom'` | `'bottom'` | Sets the loading direction. |
    | `forceUseInfiniteWrapper` | `boolean \| string` | `false` | Controls which scroll container is used: `true` for nearest `infinite-wrapper` / `data-infinite-wrapper`, string for CSS selector, fallback to `window`. |
    | `identifier` | `any` | `Date.now()` | Resets the component when the value changes (useful for filters/tabs). |
  5. Use InfiniteLoading types and interfaces

    main

    The package exports several TypeScript types and interfaces to help you type props, events, and state changes when working with the InfiniteLoading component.

    Available Types:

    • DirectionType: Defines the direction of loading (e.g., top or bottom).
    • InfiniteEvent: Represents an individual event emitted by the component.
    • InfiniteLoadingEvents: The interface for the component's event dispatcher.
    • InfiniteLoadingProps: The interface defining all available props for the InfiniteLoading component.
    • InfiniteLoadingSnippets: Defines the types for the component's snippets (e.g., spinner, loading, error, etc.).
    • SpinnerType: Defines the type for the spinner configuration.
    • StateChanger: A function type used to trigger state changes manually.
    import type {
    	DirectionType,
    	InfiniteEvent,
    	InfiniteLoadingEvents,
    	InfiniteLoadingProps,
    	InfiniteLoadingSnippets,
    	SpinnerType,
    	StateChanger
    } from 'svelte-infinite-loading';
  6. Manage loading state with StateChanger

    main

    The onInfinite event provides a StateChanger object used to communicate the status of your data fetching to the component. Use these methods inside your event handler:

    • loaded(): Call this when data is successfully fetched. If the new data doesn't fill the screen, the onInfinite event will fire again immediately. Otherwise, the component hides the spinner and waits for the next scroll event.
    • complete(): Call this when all available data has been loaded. This will trigger either the noResults or noMore snippet depending on whether data was previously loaded.
    • error(): Call this when the data fetch fails. This will trigger the error snippet.
    • reset(): Resets the component state.
    <InfiniteLoading onInfinite={async (state) => {
      try {
        const data = await fetchData();
        if (data.length > 0) {
          state.loaded();
        } else {
          state.complete();
        }
      } catch (e) {
        state.error();
      }
    }} />
  7. Use InfiniteLoading snippets

    main

    You can customize the UI for different loading states using Svelte snippets:

    • noResults: Displayed when complete() is called before any data has been successfully loaded.
    • noMore: Displayed when complete() is called after at least one successful loaded() call.
    • error: Displayed when error() is called. It receives an attemptLoad function as its first argument, which can be used to retry the data fetch.
    • spinner: Displayed during the loading process. It receives isFirstLoad (boolean) as its first argument, indicating if this is the very first data fetch.
    <InfiniteLoading>
      {#snippet noResults()}
        <p>No data found.</p>
      {/snippet}
    
      {#snippet error(attemptLoad)}
        <p>Failed to load.</p>
        <button onclick={attemptLoad}>Retry</button>
      {/snippet}
    
      {#snippet spinner(isFirstLoad)}
        {#if isFirstLoad}
          <BigSpinner />
        {:else}
          <SmallSpinner />
        {/if}
      {/snippet}
    </InfiniteLoading>
  8. Configure InfiniteLoadingProps

    main

    The InfiniteLoading component accepts the following configuration props:

    • distance (number, default: 100): The scroll distance threshold. The onInfinite event fires when the scroll position is within this distance of the target edge (top or bottom).
    • spinnerType (SpinnerType, default: 'default'): Selects a built-in loading animation. Options: 'default', 'bubbles', 'circles', 'spiral', 'wavedots'.
    • direction (DirectionType, default: 'bottom'): Sets the scroll direction to monitor. Options: 'top' or 'bottom'.
    • forceUseInfiniteWrapper (boolean | string, default: false): Defines the scroll container:
      • false: Searches for the closest parent with overflow-y: auto or scroll.
      • true: Searches for the closest parent with an infinite-wrapper or data-infinite-wrapper attribute.
      • string: Uses the provided CSS selector via querySelector to find the container.
      • If all lookups fail, it defaults to window.
    • identifier (any, default: Date.now()): A value used to reset the component. Changing this prop is equivalent to recreating the component, which is useful for resetting state when filters or tabs change.
    // Example usage of props
    <InfiniteLoading
      distance={200}
      spinnerType="bubbles"
      direction="bottom"
      forceUseInfiniteWrapper=".my-scroll-container"
      identifier={currentFilter}
    />