Git Product home page Git Product logo

react-infinite-scroller's Introduction

React Infinite Scroller

npm npm npm

Infinitely load a grid or list of items in React. This component allows you to create a simple, lightweight infinite scrolling page or element by supporting both window and scrollable elements.

  • ⏬ Ability to use window or a scrollable element
  • 📏 No need to specify item heights
  • 💬 Support for "chat history" (reverse) mode
  • ✅ Fully unit tested and used in hundreds of production sites around the world!
  • 📦 Lightweight alternative to other available React scroll libs ~ 2.2KB minified & gzipped

Installation

npm install react-infinite-scroller --save
yarn add react-infinite-scroller

How to use

import InfiniteScroll from 'react-infinite-scroller';

Window scroll events

<InfiniteScroll
    pageStart={0}
    loadMore={loadFunc}
    hasMore={true || false}
    loader={<div className="loader" key={0}>Loading ...</div>}
>
    {items} // <-- This is the content you want to load
</InfiniteScroll>

DOM scroll events

<div style="height:700px;overflow:auto;">
    <InfiniteScroll
        pageStart={0}
        loadMore={loadFunc}
        hasMore={true || false}
        loader={<div className="loader" key={0}>Loading ...</div>}
        useWindow={false}
    >
        {items}
    </InfiniteScroll>
</div>

Custom parent element

You can define a custom parentNode element to base the scroll calulations on.

<div style="height:700px;overflow:auto;" ref={(ref) => this.scrollParentRef = ref}>
    <div>
        <InfiniteScroll
            pageStart={0}
            loadMore={loadFunc}
            hasMore={true || false}
            loader={<div className="loader" key={0}>Loading ...</div>}
            useWindow={false}
            getScrollParent={() => this.scrollParentRef}
        >
            {items}
        </InfiniteScroll>
    </div>
</div>

Props

Name Required Type Default Description
children       Yes Node             Anything that can be rendered (same as PropType's Node)
loadMore       Yes Function             A callback when more items are requested by the user. Receives a single parameter specifying the page to load e.g. function handleLoadMore(page) { /* load more items here */ } }
element Component 'div' Name of the element that the component should render as.
hasMore Boolean false Whether there are more items to be loaded. Event listeners are removed if false.
initialLoad Boolean true Whether the component should load the first set of items.
isReverse Boolean false Whether new items should be loaded when user scrolls to the top of the scrollable area.
loader Component A React component to render while more items are loading. The parent component must have a unique key prop.
pageStart Number 0 The number of the first page to load, With the default of 0, the first page is 1.
getScrollParent Function Override method to return a different scroll listener if it's not the immediate parent of InfiniteScroll.
threshold Number 250 The distance in pixels before the end of the items that will trigger a call to loadMore.
useCapture Boolean false Proxy to the useCapture option of the added event listeners.
useWindow Boolean true Add scroll listeners to the window, or else, the component's parentNode.

Troubleshooting

Double or non-stop calls to loadMore

If you experience double or non-stop calls to your loadMore callback, make sure you have your CSS layout working properly before adding this component in. Calculations are made based on the height of the container (the element the component creates to wrap the items), so the height of the container must equal the entire height of the items.

.my-container {
  overflow: auto;
}

Some people have found success using react-infinite-scroll-component.

But you should just add an isLoading prop!

This component doesn't make any assumptions about what you do in terms of API calls. It's up to you to store whether you are currently loading items from an API in your state/reducers so that you don't make overlapping API calls.

loadMore() {
  if(!this.state.isLoading) {
    this.props.fetchItems();
  }
}

react-infinite-scroller's People

Contributors

ahstro avatar akichim21 avatar alexschwabauer avatar alx-khramov avatar anupvarghese avatar bukinoshita avatar chris-allen avatar danbovey avatar devpascoe avatar dlstanle avatar guillaumervls avatar handtrix avatar hengkx avatar invisiblebacon avatar jdupont avatar joaomarceloods avatar k2snowman69 avatar lapanti avatar michaeldeboey avatar mrdivyansh avatar nagogus avatar ruipserra avatar skovy avatar stanleysathler avatar trevorhinesley avatar vanhtuan0409 avatar vjeux avatar zclark avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-infinite-scroller's Issues

loadMore not called

loadMore() { console.log('------> LOAD MORE') this.setState({ ...this.state, pageStart: this.state.pageStart++ }) }

<InfiniteScroll initialLoad={ false } pageStart={ this.state.pageStart } loadMore={ this.loadMore } hasMore={ this.state.hasMore } /* always true */ threshold={ 50 } useWindow={ false } loader={ loader }> ...content </InfiniteScroll>

loadMore function is not called. Can you tell me please why i'm encountering this problem ?

thank you !

loading forever without stopping on safari mobile

Hi,

I noticed on safari mobile that it loads forever when initially loading the page. I have useWindow=false.

I looked at this line:

offset = el.offsetHeight - el.parentNode.scrollTop - el.parentNode.clientHeight;

It seems new elements are loaded if offset is larger than the threshold.And offset never changed even when loading elements.

Elements in my scenario are added to the bottom of the list.scrollTop is always 0 and clientHeight is the size of the viewable container.

The offsetHeight property returns the viewable height of an element in pixels, including padding, border and scrollbar, but not the margin.

If change this to el.scrollHeight it seems to work.

The scrollHeight property should return the height independent of whether it is viewable or not.

offset = el.scrollHeight - el.parentNode.scrollTop - el.parentNode.clientHeight;

best regards,
Florian

Fix README to remove npm reference?

The npm reference is still guillaumervls's older version without the updates. It might be good to at least remove that reference from the README until you create your own npm package?

Support only rendering part of the contents

I'm using react-infinite-scroller to load a large list of images and it is working great. I start by loading the first 10 images. However I only want to show 30 images on screen at once so once 30 images have been loaded I start to not render those near the top of the page. But now if the user scrolls back up the page they won't see those images anymore so I want some sort of trigger to begin showing those again.

I know this isn't a straightforward feature but I'm thinking that in addition to loadMore there could be a loadTop that would fire when the user begins scrolling back up towards the top of the page (based on a topThreshold) that could be used to figure out which 30 images to show (near the top or near the bottom of the list).

Is this something that is in scope for this project? I could work-around it by attaching my own scroll listener and logic to the container but I'd rather not reimplement that code in my project.

Feature request : Debounce the scrollListener

Hi,
I've passed some time trying to update the orginal react-infinite-scroller and shame on me, I didn't see your fork.

I ended making some improvements on the original script (the one your forked), but the most efficient change I did was to debounce the position checking and loadMore things. I've adapted to my needs, hope it's readable.

The idea is very simple :

  • in the constructor, you set a this.debounceTimeout to null
  • in the scrollListener you check if this.debounceTimeout is null. If yes, you set it to a setTimeout(load_more_if_needed, 250), if not you just pass your way.

As a window.addEventListener("scroll", this.scrollListener); will fire scrollListener a lot of time, and very fast, it's gonna do some calculations all the time. it's better explained there.

I don't have time and enery to make a pull request from your fork, sorry.

Possible bug

I am getting an infinite loop issue
This may be related to #14 and #18

I tried both solutions with no luck

So I did some investigation and I only can relate the whole thing to this line
which is essentially executes this.scrollListener() Which I am not sure why would you call that method after attaching it to an event.

Unless I am missing something, when I commented out that line everything went as expected.

lower dependency version

I am using react 0.14.3 and the component works. the only issue is that it gives conflicts whenever i try to save it to the package.json

It's not possible to have more than one instance of the component

Currently the way it's coded with use of

var component;

you can only have one InfiniteScroller!

Just a simple fix to change lines like

var el = ReactDOM.findDOMNode(component);

into

var el = ReactDOM.findDOMNode(this);

and binding the scroll event listeners properly 😑

Load more for <table>

Hi!
How it use for table tag ?
<table><thead></thead><InfiniteScroll><tr>Item</tr><tr>Item</tr><tr>Item</tr></InfiniteScroll></table>

Settings
element="tbody" pageStart={1} loadMore={this.loadItems.bind(this)} hasMore
Event don't working, when user scroll items.
Thx for help!

Implement formal testing

First commit (57c8ef3) was for Cassette's requirements but that could break in others' use cases.

Some formal testing in mocha or similar 💯

Calls `loadMore` endlessly

Why would the component call loadMore continuously and endlessly with increasing page numbers once I reach (only once) the end of the list? What am I doing wrong? FYI, I am using redux for this.

Thanks!

Add a `component` or `wrapper` prop to chose what container element it should render

It would be great to have a component (or wrapper) prop that would allow to chose the container element, ie:

<InfiniteScroll
      pageStart={0}
      loadMore={loadFunc}
      hasMore={true || false}
      component={<ul className="my-list">{props.children}</ul>}
      loader={<div className="loader">Loading ...</div>}>
    {items} // <-- This is the content you want to load
  </InfiniteScroll>

v1.0.9 Unable to resolve path to module 'react-infinite-scroller'

Hi, after the update we are getting this lint error Unable to resolve path to module 'react-infinite-scroller' when the package is imported this way (as it used to be) import InfiniteScroll from 'react-infinite-scroller'; . There must be something wrong with the package configuration since I am able to import the package as import InfiniteScroll from 'react-infinite-scroller/dist/InfiniteScroll';

Is there a way to reset the current page?

Adding this issue because it was asked to me directly.

If you're filtering items, and the data needs to be completely changed, the page needs to be reset back to pageStart.

One solution is adding a method to the component: guillaumervls#29

But really, if you need your own pagination methods, you should handle it in the state of your own component and ignore the pageToLoad parameter that you're given.

Throttle scrollListener

Would be nice to have a throttle option for the scrollListener function (limit firing of the event). Could probably pull most of the code from underscore.

Dom scroll parent with unfixed height

Currently working on a project where the wrapper, which can be scrolled, has following styling:

.style {
    height: 100%;
    overflow-y: auto;
}

In this case offset needs to be calculated like this:

offset = el.parentNode.scrollHeight - el.parentNode.scrollTop - el.parentNode.clientHeight;

instead of this:

offset = el.scrollHeight - el.parentNode.scrollTop - el.parentNode.clientHeight;

How about a prop (boolean) relativeParentHeight?

Permanent loading of more results in iFrame with dynamic height

Hi,

I encountered a sweet little problem when using the InfiniteScroller inside of an iFrame.
The iFrame is called a ContentFrame in the Content Management System.
The CMS Editor UI automatically updates the iFrames height to the documents height to prevent the iFrame from having scrollbars.

This triggers a permanent loadMore in the InfiniteScroller.
I think the calculation for the threshold value is currently not flexible enough to cover this case.

If offset and threshold comparison operator

Wouldn't it make more sense to change the comparsion operator from

if (offset < Number(this.props.threshold))

to

if (offset <= Number(this.props.threshold))

Otherwise someone would need to pass threshold={1} to get a true at 0 offset.

Does not wait for loadmore to finish before calling again

It seems to fire off 2 or 3 calls to loadMore while my loadMore is off making a network request to get the items. Would it perhaps make sense to add some way for us to confirm that loadMore is completed before another request is fired off?

Demo link?

Hi! I was looking to try it out and was wondering if it is possible to have a demo link for the project? The original project's demo link doesn't work either and since this is being maintained, it would be great to have one to check out the plugin!

Thanks for maintaining this!

Reverse scrolling

It would be great if this component would support a boolean property like flipped or reversed or something that would invert the scrolling. This is ideal for lists that start at the bottom like chat messages.

Data is loaded correctly but component will not get the latest data

I am using "react-infinite-scroller": "^1.0.11". It looks good but I am running into a problem. Here is how to regenerate the issue.

  1. I load a component that makes use of InfiniteScroll.
  2. The component receives the first chunk of data with no issues.
  3. I scroll down to the end, the next chunk of data get loaded and the component gets updated with all data (previous and new). So everything is good so far.
  4. Now, I turn the network off. I scroll to the bottom of the page, but obviously I run into Network error which is expected.
  5. Now, I turn the network on. I scroll to the bottom of the page, new data comes back from the server BUT the new data never show up in the component. So component render with old data. For some reason. The component never see the new data even though I am very sure that the new data was loaded.
    I tried the test on the demo and same result appears.
    Could you please let me know if there is a fix to this.
    Thanks

Will you help with this?

I'm using this with backbone. But I'm not getting expected result. the browser is keep on hitting the server and getting the data. I didn't even started scrolling. It's not getting stopped.

Issue with topPosition computing when useWindow

I'm using this comp because unlike this one, it doesn't require to know the inner elements heights.

However, I have an issue when using it with useWindow=true.

It compute a topPosition(el)= 9961 so that the threesold is never reached...

Have you experienced this issue as well ?

Load items on scroll top AND scroll bottom

Hi everyone!

Is it possible to give an extra parameter to the loadMore function, so I can know if it's pulled from the top or scrolled to the bottom?

I'm making a Mail-webclient and initialize the list of Mails with the first 25 mails.
When I scroll down I want to load the next 25, ...
But when I scroll to the top I want to load the first page again.
Is this possible in any way?
The page-number is always additioning so... :/

Loading all content without scrolling

I am making ajax request 5 times and updating my "items" array on each request. But InfiniteScroll Component is loading all data at once. It does not wait me to scroll and then load the further data. Please help.

cannot resolve module 'prop-types'

src used prop-types
import PropTypes from 'prop-types';
but prop-types defined in package's devDependencies
so after i installed, can not resolve module 'prop-typs',
should prop-types in package defined in dependencies?

Requiring the lib

Hey, I've installed the package via NPM and require it as follows:

var InfiniteScroll = require('react-infinite-scroller');

Apparently, something goes wrong as I have a react error:

React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components). Check the render method of Search.

To what I see, the require returns a function. Probably I require it in a wrong way (although I do it in the same way I require other react libs). Maybe the solution is in your phrase "require with main in package.json", but I can't figure out what does it mean. Can you help? Thanks.

Use 'react-proptypes' instead of React.PropTypes

React.PropTypes has been extracted to it's own package since React v15.5.0.

The following warning is displayed if that version of React is used:

Warning: Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead.

Scrolling to bottom of container will cause infinite fetching

I created a test component to begin working the the infinite scroller and found an issue with scrolling to the bottom of the wrapper div: it won't stop fetching. I noticed your docs example will push the new items down, but my scrollbar seems to stick at the bottom. Is this a CSS issue? I'm open to any quick fix so that these lists don't infinitely fetch.

screen shot 2017-02-17 at 11 52 10 am

import React, { Component }  from 'react';
import InfiniteScroll from 'react-infinite-scroller';

function createNumbersArray(start, length) {
  const arr = new Array(length);
  for (let i = 0; i < arr.length; i++) {
    arr[i] = start + i;
  }

  return arr;
}

function fetchNumbers(start, length) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      try {
        const newNumbers = createNumbersArray(start, length);
        resolve(newNumbers);
      } catch (err) {
        reject(err);
      }
    }, 3000);
  });
}

const LIMIT = 10;

export default class TestInfiniteScroll extends Component {
  constructor(props) {
    super(props);

    this.state = {
      items: [],

      // Was too lazy and this fixed initial load at 0, 10
      start: -10,
    };

    this.loadMore = this.loadMore.bind(this);
  }

  componentDidMount() {
    this.loadMore();
  }

  loadMore() {
    console.log('FETCHING MORE');
    const oldItems = this.state.items;
    const start = this.state.start + LIMIT;
    fetchNumbers(start, LIMIT)
      .then(newItems => this.setState({ items: [...oldItems, ...newItems], start }))
      .catch(err => console.log(err));
  }

  render() {
    const { items } = this.state;
    const itemComponents = items.map((item) => {
      return (
        <div
          style={{ height: '50px', padding: '5px', border: '1px solid grey', backgroundColor: 'white' }}
          key={Date.now() + item}
        >
          {item}
        </div>
      );
    });

    const hasMore = items.length < 100;
    return (
      <div>
        <h1>InfiniteScroll</h1>
        <div style={{ height: '400px', overflow: 'auto', border: '2px solid' }}>
          <InfiniteScroll
            pageStart={0}
            loadMore={this.loadMore}
            hasMore={hasMore}
            loader={<div>Loading ...</div>}
            useWindow={false}
            threshold={5}
          >
            {itemComponents}
          </InfiniteScroll>
        </div>
      </div>
    );
  }
}

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.