GithubHelp home page GithubHelp logo

nevendyulgerov / react-infi-scroller Goto Github PK

View Code? Open in Web Editor NEW
0.0 1.0 0.0 923 KB

React-based infinite scroll component

License: MIT License

JavaScript 55.08% TypeScript 44.92%
react infinite-scroll javascript typescript prop-types

react-infi-scroller's Introduction

React Infi Scroller

npm npm

React-based infinite scroll component that just works. It supports window and scrollable nodes, without inline style for height.

Installation

To install the component, run:

npm install react-infi-scroller

How to use

To import the component in your project:

import InfiScroller from 'react-infi-scroller';

Use InfiScroller on the window object:

import React, { useState } from 'react';
import InfiScroller from 'react-infi-scroller';

const MyComponent = () => {
  const generateItems = (items = [], length = 30) => {
    const nextItems = [...items];
    for (let i = 0; i < length; i += 1) {
      nextItems.push(items.length + i);
    }
    return nextItems;
  };
  const [items, setItems] = useState(generateItems());
  const [hasMore, setHasMore] = useState(true);

  return (
    <InfiScroller
      hasMore={hasMore}
      onLoadMore={() => {
        const nextItems = generateItems(items);
        setItems(nextItems);
        setHasMore(nextItems.length < 300);
      }}
    >
      <ul>
        {items.map((item) => (
          <li
            key={item}
            style={{ height: 100 }}
          >
            {`Item ${item}`}
          </li>
        ))}
      </ul>
    </InfiScroller>
  );
};

Use InfiScroller on a custom scroll target (like a modal):

import React, { useState, useRef } from 'react';
import InfiScroller from 'react-infi-scroller';

const MyComponent = () => {
  const generateItems = (items = [], length = 30) => {
    const nextItems = [...items];
    for (let i = 0; i < length; i += 1) {
      nextItems.push(items.length + i);
    }
    return nextItems;
  };
  const [items, setItems] = useState(generateItems());
  const [hasMore, setHasMore] = useState(true);
  const refComponent = useRef(null);

  return (
    <div ref={refComponent}>
      <InfiScroller
        scrollTarget={refComponent.current}
        hasMore={hasMore}
        onLoadMore={() => {
          const nextItems = generateItems(items);
          setItems(nextItems);
          setHasMore(nextItems.length < 300);
        }}
      >
        <ul>
          {items.map((item) => (
            <li
              key={item}
              style={{ height: 100 }}
            >
              {`Item ${item}`}
            </li>
          ))}
        </ul>
      </InfiScroller>
    </div>
  );
};

Use multiple InfiScroller components with custom scroll targets:

import React, { useState, useRef } from 'react';
import InfiScroller from 'react-infi-scroller';

const MyComponent = () => {
  const generateItems = (items = [], length = 30) => {
    const nextItems = [...items];
    for (let i = 0; i < length; i += 1) {
      nextItems.push(items.length + i);
    }
    return nextItems;
  };
  const [items, setItems] = useState(generateItems());
  const [hasMore, setHasMore] = useState(true);
  const [otherItems, setOtherItems] = useState(generateItems());
  const [hasMoreOther, setHasMoreOther] = useState(true);
  const refItemsWrapper = useRef(null);
  const refOtherItemsWrapper = useRef(null);
  
  /* Styles for the scroll targets used below
  <style>
    .items-scroller {
      height: 300px;
      overflow: auto;
      background-color: white;
    }

    .other-items-scroller {
      height: 500px;
      margin-top: 40px;
      overflow: auto;
      background-color: white;
    }
  </style>
  */

  return (
    <div>
      <div
        ref={refItemsWrapper}
        className="items-scroller"
      >
          <InfiScroller
            scrollTarget={refItemsWrapper.current}
            hasMore={hasMore}
            onLoadMore={() => {
              const nextItems = generateItems(items);
              setItems(nextItems);
              setHasMore(nextItems.length < 300);
            }}
          >
            <ul>
              {items.map((item) => (
                <li
                  key={item}
                  style={{ height: 100 }}
                >
                  {`Item ${item}`}
                </li>
              ))}
            </ul>
          </InfiScroller>
      </div>

      <div
        ref={refOtherItemsWrapper}
        className="other-items-scroller"
      >
          <InfiScroller
            scrollTarget={refOtherItemsWrapper.current}
            hasMore={hasMoreOther}
            onLoadMore={() => {
              const nextOtherItems = generateItems(otherItems);
              setOtherItems(nextOtherItems);
              setHasMoreOther(nextOtherItems.length < 120);
            }}
          >
            <ul>
              {otherItems.map((otherItem) => (
                <li
                  key={otherItem}
                  style={{ height: 100 }}
                >
                  {`Other Item ${otherItem}`}
                </li>
              ))}
            </ul>
          </InfiScroller>
      </div>
    </div>
  );
};

Use InfiScroller with a spinner/loader:

import React, { useState } from 'react';
import InfiScroller from 'react-infi-scroller';

const MyComponent = () => {
  const generateItems = (items = [], length = 30) => {
    const nextItems = [...items];
    for (let i = 0; i < length; i += 1) {
      nextItems.push(items.length + i);
    }
    return nextItems;
  };
  const [items, setItems] = useState(generateItems());
  const [hasMore, setHasMore] = useState(true);

  return (
    <InfiScroller
      hasMore={hasMore}
      onLoadMore={() => {
        const nextItems = generateItems(items);
        setItems(nextItems);
        setHasMore(nextItems.length < 300);
      }}
    >
      <ul>
        {items.map((item) => (
          <li
            key={item}
            style={{ height: 100 }}
          >
            {`Item ${item}`}
          </li>
        ))}
      </ul>

      {hasMore && (
        <span>Loading...</span>
      )}
    </InfiScroller>
  );
};

Props

Name Type Default Description
children Node | NodeList The content in the infinite scroller. Contains the list of items you want to trigger infinite scrolling for.
scrollTarget Node null The scroll target. Can be set to a custom scrollable node or omitted/null. When omitted/null the window object is used as scroll target.
debounceDelay Number 300 Debounce delay (in milliseconds) to optimize high-frequency scroll events. A recommended delay of 300 milliseconds is set by default.
gutter Number 10 Additional space (in pixels) used in the default shouldLoadMore calculation. Increasing it will cause the onLoadMore callback to be called before the scrollbar has reached the bottom of the scrollTarget. The larger the number, the earlier the onLoadMore callback will be called. A recommended minimum gutter of 10 pixels is set by default.
immediate Boolean false Whether to trigger an initial check, before any scroll event, if onLoadMore callback should be called. Set it to truewhen you want onLoadMore to be called immediately after the scrollTarget is mounted. This can be useful in case the scrollbar has been preset to the bottom of the scrollTarget or the content of the scrollTarget is less than its height and no scroll exist for it yet.
active Boolean true Turn on/off the infinite scroller. Keeps the component's children visible. Attaches event listeners when set to true. Detaches event listeners when set to false. Useful when the infinite scroller is placed inside a modal and you want it disabled until the modal is activated.
hasMore Boolean false Whether there are more items to load. This flag is used to determine if onLoadMore should be called. The entire check looks like this hasMore && shouldLoadMore(...).
shouldLoadMore
(
 scrollTargetHeight: number,
 scrollYOffset: number,
 gutter: number,
 scrollHeight: number
) => boolean
(
 scrollTargetHeight,
 scrollYOffset,
 gutter,
 scrollHeight
) => (
  scrollTargetHeight
  + scrollYOffset
  + gutter
  >= scrollHeight
)
Determine if more items should be loaded. By default a scrollTargetHeight + scrollYOffset + gutter >= scrollHeight formula is used. Provide a different function to customize this behavior. Note that shouldLoadMore will be called only if hasMore is true.
onLoadMore () => void Called when hasMore && shouldLoadMore(...) is true. You should load and render more items in the infinite scroller when onLoadMore is called.

react-infi-scroller's People

Contributors

nevendyulgerov avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.