Git Product home page Git Product logo

react-infinite's Introduction

React Infinite

Build Status Coverage Status npm version bitHound Score

A browser-ready efficient scrolling container based on UITableView.

React Infinite 0.7.1 only supports React 0.14 and above. Please pin your package to 0.6.0 for React 0.13 support.

When a long list of DOM elements are placed in a scrollable container, all of them are kept in the DOM even when they are out the user's view. This is highly inefficient, especially in cases when scrolling lists can be tens or hundreds of thousands of items long. React Infinite solves this by rendering only DOM nodes that the user is able to see or might soon see. Other DOM nodes are clustered and rendered as a single blank node.

Installation

In the Browser

The relevant files are dist/react-infinite.js and dist/react-infinite.min.js. You must have React available as a global variable named React on the window. Including either file, through concatenation or a script tag, will produce a global variable named Infinite representing the component.

In NPM

React Infinite uses a Universal Module Definition so you can use it in NPM as well. npm install this package and

var Infinite = require('react-infinite');

In Browserify

If you want to use the source with Browserify, the ES5-compiled source is directly requirable from the /build folder off NPM.

Otherwise, you can follow the instructions for NPM.

Basic Use

Elements of Equal Height

To use React Infinite with a list of elements you want to make scrollable, provide them to React Infinite as children.

<Infinite containerHeight={200} elementHeight={40}>
    <div className="one"/>
    <div className="two"/>
    <div className="three"/>
</Infinite>

Elements of Varying Heights

If not all of the children have the same height, you must provide an array of integers to the elementHeight prop instead.

<Infinite containerHeight={200} elementHeight={[111, 252, 143]}>
    <div className="111-px"/>
    <div className="252-px"/>
    <div className="143-px"/>
</Infinite>

Using the Window to Scroll (useWindowAsScrollContainer mode)

To use the entire window as a scroll container instead of just a single div (thus using window.scrollY instead of a DOM element's scrollTop), add the useWindowAsScrollContainer prop.

<Infinite containerHeight={200} elementHeight={[111, 252, 143]}
          useWindowAsScrollContainer>
    <div className="111-px"/>
    <div className="252-px"/>
    <div className="143-px"/>
</Infinite>

As A Chat or Message Box (displayBottomUpwards mode)

React Infinite now supports being used as a chat box, i.e. appended elements appear at the bottom when added, and the loading of the next page occurs when the user scrolls to the top of the container. To do so, simply add the displayBottomUpwards prop. A sample implementation can be consulted for more information - run gulp develop to compile the example files.

<Infinite containerHeight={200} elementHeight={[111, 252, 143]}
          displayBottomUpwards>
    // insert messages for subsequent pages at this point
    <div className="third-latest-chat"/>
    <div className="second-latest-chat"/>
    <div className="latest-chat-message"/>
</Infinite>

Note on Smooth Scrolling

A wrapper div is applied that disables pointer events on the children for a default of 150 milliseconds after the last user scroll action for browsers with inertial scrolling. To configure this, set timeScrollStateLastsForAfterUserScrolls.

Static Methods

Function Infinite.containerHeightScaleFactor(Number number)

This function allows a value to be specified for preloadBatchSize and preloadAdditionalHeight that is a relative to the container height. Please see the documentation for those two configuration options for further information on how to use it.

Configuration Options

Children

The children of the <Infinite> element are the components you want to render. This gives you as much flexibility as you need in the presentation of those components. Each child can be a different component if you desire. If you wish to render a set of children not all of which have the same height, you must map each component in the children array to an number representing its height and pass it in as the elementHeight prop.

Major Display Modes

By default, React Infinite renders a single element with the provided containerHeight, and the list sticks to the top like a regular table. However, you can choose to use the entire window as the scroll container or make React Infinite like a chatbox with the following options. They can be used together if you wish.

Bool useWindowAsScrollContainer

Defaults to false. This option allows the window to be used as the scroll container, instead of an arbitrary div, when it is set to true. This means that scroll position is detected by window.scrollY instead of the scrollTop of the div that React Infinite creates. Using this option is a way of achieving smoother scrolling on mobile before the problem is solved for container divs.

Bool displayBottomUpwards

Defaults to false. This allows React Infinite to be used as a chatbox. This means that the scroll is stuck to the bottom by default, and the user scrolls up to the top of the container to load the next page. The children are displayed in the same order.

Configuration Options

(Required) Number | [Number] elementHeight

If each child element has the same height, you can pass a number representing that height as the elementHeight prop. If the children do not all have the same height, you can pass an array which is a map the children to numbers representing their heights to the elementHeight prop.

Number containerHeight

The height of the scrolling container in pixels. This is a required prop if useWindowAsScrollContainer is not set to true.

Number | Object preloadBatchSize

Defaults to this.props.containerHeight * 0.5. Imagine the total height of the scrollable divs. Now divide this equally into blocks preloadBatchSize pixels high. Every time the container's scrollTop enters each of these blocks the set of elements rendered in full are those contained within the block and elements that are within preloadAdditionalHeight above and below it.

When working with the window as the scroll container, it is sometimes useful to specify a scale factor relative to the container height as the batch size, so your code does not need to know anything about the window. To do this, use Infinite.containerHeightScaleFactor. So, for example, if you want the preloaded batch size to be twice the container height, write preloadBatchSize={Infinite.containerHeightScaleFactor(2)}.

Number | Object preloadAdditionalHeight

Defaults to this.props.containerHeight. The total height of the area in which elements are rendered in full is height of the current scroll block (see preloadBatchSize) as well as preloadAdditionalHeight above and below it.

When working with the window as the scroll container, it is sometimes useful to specify this relative to the container height. If you want the preloaded additional height to be twice the container height, write preloadAdditionalHeight={Infinite.containerHeightScaleFactor(2)}. Please see preloadBatchSize for more details.

Function handleScroll(DOMNode node)

Defaults to function(){}. A function that is called when the container is scrolled, i.e. when the onScroll event of the infinite scrolling container is fired. The only argument passed to it is the native DOM Node of the scrolling container.

Number infiniteLoadBeginEdgeOffset

Defaults to undefined, which means that infinite loading is disabled. To disable infinite loading, do not provide this property or set it to undefined.

Regular Mode When the user reaches this number of pixels from the bottom, the infinite load sequence will be triggered by showing the infinite load spinner delegate and calling the function onInfiniteLoad.

displayBottomUpwards mode When the user reaches this number of pixels from the top of the container, the infinite load sequence will be triggered by showing the infinite loading spinner delegate at the top of the container and calling onInfiniteLoad.

Function onInfiniteLoad()

Defaults to function(){}. This function is called when the scroll exceeds infiniteLoadBeginEdgeOffset. Before this function is called, the infinite loading spinner is automatically turned on. You can set up infinite scrolling with this function like this:

  1. Fetch a new page of records from the appropriate API
  2. When the AJAX call returns, send the new list of elements (with the items that were just fetched) back as the children of React Infinite.
  3. Set React Infinite's isInfiniteLoading prop to false to hide the loading spinner display

onInfiniteLoad relies heavily on passing props as a means of communication in the style of idiomatic React.

React Node loadingSpinnerDelegate

Defaults to <div/>. The element that is provided is used to render the loading view when React Infinite's isInfiniteLoading property is set to true. A React Node is anything that satisfies React.PropTypes.node.

Bool isInfiniteLoading

Defaults to false. This property determines whether the infinite spinner is showing.

Number timeScrollStateLastsForAfterUserScrolls

Defaults to 150 (in milliseconds). On Apple and some other devices, scroll is inertial. This means that the window continues to scroll for several hundred milliseconds after an onScroll event is fired. To prevent janky behavior, we do not want pointer-events to reactivate before the window has finished moving. Setting this parameter causes the Infinite component to think that the user is still scrolling for the specified number of milliseconds after the last onScroll event is received.

String className

Allows a CSS class to be set on the scrollable container.

Sample Code

Code samples are now available in the /examples directory for your perusal. Two examples are provided, one for constant height with infinite loading and another with random variable heights with infinite loading. To generate the files necessary for the examples, execute npm install && gulp build -E. You may need to first install gulp with npm install -g gulp.

To get you started, here is some sample code that implements an infinite scroll with an simulated delay of 2.5 seconds. A live demo of this example is available on our blog.

var createReactClass = require('create-react-class');

var ListItem = createReactClass({
    render: function() {
        return <div className="infinite-list-item">
        List Item {this.props.num}
        </div>;
    }
});

var InfiniteList = createReactClass({
    getInitialState: function() {
        return {
            elements: this.buildElements(0, 20),
            isInfiniteLoading: false
        }
    },

    buildElements: function(start, end) {
        var elements = [];
        for (var i = start; i < end; i++) {
            elements.push(<ListItem key={i} num={i}/>)
        }
        return elements;
    },

    handleInfiniteLoad: function() {
        var that = this;
        this.setState({
            isInfiniteLoading: true
        });
        setTimeout(function() {
            var elemLength = that.state.elements.length,
                newElements = that.buildElements(elemLength, elemLength + 1000);
            that.setState({
                isInfiniteLoading: false,
                elements: that.state.elements.concat(newElements)
            });
        }, 2500);
    },

    elementInfiniteLoad: function() {
        return <div className="infinite-list-item">
            Loading...
        </div>;
    },

    render: function() {
        return <Infinite elementHeight={40}
                         containerHeight={250}
                         infiniteLoadBeginEdgeOffset={200}
                         onInfiniteLoad={this.handleInfiniteLoad}
                         loadingSpinnerDelegate={this.elementInfiniteLoad()}
                         isInfiniteLoading={this.state.isInfiniteLoading}
                         >
            {this.state.elements}
        </Infinite>;
    }
});

ReactDOM.render(<InfiniteList/>, document.getElementById('react-example-one'));

SeatGeek also currently uses React Infinite in production on our event pages; because we only have pages for events in the future, a link would not be appropriate. To see one, head to one of our team pages for the New York Giants, or the New York Mets, or the New York Knicks, and click on the green button for an event to see them in action in the Omnibox.

Contributing to React Infinite

Useful notes for how to contribute are available.

react-infinite's People

Contributors

ahutchings avatar basketofsoftkittens avatar daveschumaker avatar dustingetz avatar erwaller avatar eudisd avatar frederickfogerty avatar garetht avatar grigy avatar hledley avatar jayfunk avatar jessicard avatar kgregory avatar mashehu avatar oliviertassinari avatar sarmadsangi avatar supremetechnopriest avatar taish avatar thaggie avatar titipakorn avatar zackkitzmiller 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  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

react-infinite's Issues

Why do you need containerHeight?

Hi,

Why do you need to know/specify containerHeight? I was playing with the Semantic UI infinite scroll and it detects the bottom of a DOM element i.e. a <div> automatically without specifying the height of the <div> container.

Here's a JSfiddle with Semantic UI's visibility for infinite scroll:
https://jsfiddle.net/4p6d7x86/13/

Scroll Position is changed issue

Hi,

I am integrating this plugin in mobile devices. But I am having an issue when the scroll reaches the end of the page it will be jumped up about 40-100px. So that I never see a few elements that show at the end of the page. (I have though about solution, I may remove an event when the scroll reaches the last row of element. Not sure yet if this is possible.)

This also happens sometimes when scrolling. The scroll position doesn't stay where I expected.

Appreciate your advice. Thanks.

scrollToTop() ?

Hi
It will be nice if we have scropllToTop() method on mounted component ?

Browser scroll

Hello,

I was wondering if it's possible to have a container that uses the scroll bar of the browser instead of it's own, without necessarily to be a full window container.

Thanks for your time

Scroll stutter behavior when mouse over text/content

I was able to reproduce this bug in the react-infinite demo here: http://chairnerd.seatgeek.com/react-infinite-a-browser-ready-efficient-scrolling-container-based-on-uitableview/

If the cursor is hovered over the left or right whitespace within the scrollable container, the scrolling is smooth and works as expected. However, if you hover the mouse over text and try to scroll, the inertial scrolling will promptly halt and the scroll event will bubble up to the container.

Here is a video demonstrating this behavior: http://files.ryanberdeen.com/YoGC

/cc @also

Variable heights - how to know heights before they get rendered?

array_infinite_computer needs to know the heights in advance. I'm building a chat app that doesnt know the height of the messages until they are in the dom. Can I do this without a custom computer? Seems like I could do this with a custom computer since all the computer methods needing height data are only called from life cycle methods after the relevant dom is on the page, has anybody done this?

Can't load more elements if the initial elements don't cause a scrollbar to appear

Since react-infinite can only load more items in response to a scroll event, if there's not enough loaded at the start to enable scrolling the user is stuck.

For now I have a workaround like this on my wrapper:

    componentDidUpdate(prevProps: object, prevState: object) {
        let element = React.findDOMNode(this);

        if (this.state.initialLoad) {
            if (element.clientHeight === element.scrollHeight) {
                // didn't load enough to enable scrolling yet
                if (!this.state.isInfiniteLoading) {
                    console.log("loading more at initial");
                    this.handleInfiniteLoad();
                }
            } else {
                this.setState({
                    initialLoad: false
                });
            }
        }
    }

Can a similar check be done internally to the <Infinite/> component instead?

Let me know if you need a demo of this issue.

Animations

Using react-infinite with the ReactCSSTransitionGroup results in the current buffer repeating when scrolling. Not quite sure why this happens. If anyone has ideas for a fix I'd love to hear it! Thanks!

Performance is poor on mobile devices

I have utilized this in the context of a series of <img> elements for a mobile app. While testing on desktop, this works excellently, but on my Samsung Galaxy SIII, the scrolling performance is not great - either on Chrome or Android browser. I can easily scroll faster than the container can keep up and have to wait a very long time for items to render. There's also some jitter. Are there plans to optimize the performance of this?

Updating the table while maintaining the scroll position

Hi,

Thanks for taking the time to write this module.

I'm trying to build a real-time data feed where new messages are prepended to the top of the list. But I only want to render an updated list if the user is viewing the top-most List item. If the user is scrolling somewhere down the list, then I don't want to render. Trying to read a moving list is really annoying.

It's not clear to me how to get the List items displayed in the viewport (i.e. how do I get the List items that are only displayed on the screen)? My approach was to look for the ID of the top-most displayed List item, and make sure it matches the last rendered List item. If not, then (presumably) the user is viewing a List item further down the list. Curious if you have a better approach (?)

I also wasn't sure how to read the "node" object from handleScroll.

handleScroll: function(node) {
},

what's inside that node object, and how is everyone using it.

Thanks!

Inconsistent onInfiniteLoad() calls

It's like react-infinite never realizes that it has hit the bottom of the list. The onInfiniteLoad() inconsistently fires. Sometimes it isn't called, sometimes it is called once, but it is NEVER called more than once.

Anyone else having this issue or think they may know what is wrong? I've messed with the props and left them as defaults and nothing works.

Allow customization of containing element.

I'd love to use this easily for infinite scrolling a table, where the child element would be a tbody (with some thead above it). Does this sound feasible as an addition? I'd be happy to submit a PR to get it in.

How to efficiently calculate the height between text boxes?

I'm using your library for a highly curated twitter feed, and I've found that the "heights" [or more precisely the separation between the text boxes] is a function of both the number of characters in the message (I've limited them to 140), which directly affects the number of lines being used, the way the text gets wrapped, which depends on the spacing, and the output device (i.e. the resolution of the screen, iPhone 5, vs 6, vs 6+). I'm curious, there are a lot of different cases here, is there a simple way of solving this problem? My approach involves lots of "if" statements, and it's just a hack. It's tricky since the width of the box is constantly changing...

Get initial elements from onInfiniteLoad

Why does this require initial elements in the state before first rendering?
Wouldn't it be a lot better if building the Infinite, it would first time trigger the loading of elements. This would reduce complexity required to load elements multiple ways and displaying the normal loading elements even while loading the first elements?

Type Error

Hi ,

On my first try using react-infinite i got runtime type error :

""
TypeError: ({_owner:{props:{data:[]}, _owner:{props:{}, _owner:{props:{}, _owner:null, _lifeCycleState:"MOUNTED", _pendingProps:null, _pendingCallbacks:null, _pendingOwner:null, refs:{}, state:null, _pendingState:null, context:null, _currentContext:{}, _pendingContext:null, _descriptor:{__realComponentInstance:{}}, _compositeLifeCycleState:null, _rootNodeID:".0", _mountDepth:0, _defaultProps:null, getDOMNode:(function () {
"use strict";

  return method.apply(component, arguments);
}), _pendingForceUpdate:false, _renderedComponent:{}}, _lifeCycleState:"MOUNTED", _pendingProps:null, _pendingCallbacks:null, _pendingOwner:{props:{}, _owner:null, _lifeCycleState:"MOUNTED", _pendingProps:null, _pendingCallbacks:null, _pendingOwner:null, refs:{}, state:null, _pendingState:null, context:null, _currentContext:{}, _pendingContext:null, _descriptor:{__realComponentInstance:{}}, _compositeLifeCycleState:null, _rootNodeID:".0", _mountDepth:0, _defaultProps:null, getDOMNode:(function () {

"
""
same with the example.

Support only having a single child

When my app loads it only has a single div, but as the data loads from the server it pushes more children under the scroll component.

When it loads with only one child, however, the component throws an error since it tries to slice an object.

It would be simple to change the render method of react-infinite.js to:

    var displayables = [].concat(this.props.children).slice(this.state.displayIndexStart,
                                                 this.state.displayIndexEnd + 1);

to handle this use case. Is there any reason why it should throw with only one child? Doesn't make sense to me, as children are often tied to data.

Window as the container

I haven't tried out the library, but would like to. However, I haven't seen an example of having the window as the container. Would this be correct?

<InfiniteScroll containerHeight={window.innerHeight}>
  ...
</InfiniteScroll>

Can't include react-infinite with npm

Trying to include react-infinite in a project that uses browserify results in an error. I believe this is because the package.json file points to an already browserified file.

Error: module "./computers/constant_infinite_computer.js" not found from "/home/travis/tmp/crossfilter/node_modules/react-infinite/dist/react-infinite.js"
    at notFound (/home/travis/tmp/crossfilter/node_modules/gulp-browserify/node_modules/browserify/index.js:803:15)
    at /home/travis/tmp/crossfilter/node_modules/gulp-browserify/node_modules/browserify/index.js:754:23
    at /home/travis/tmp/crossfilter/node_modules/gulp-browserify/node_modules/browserify/node_modules/browser-resolve/index.js:185:24
    at /home/travis/tmp/crossfilter/node_modules/gulp-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:36:22
    at load (/home/travis/tmp/crossfilter/node_modules/gulp-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:54:43)
    at /home/travis/tmp/crossfilter/node_modules/gulp-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:60:22
    at /home/travis/tmp/crossfilter/node_modules/gulp-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:16:47
    at FSReqWrap.oncomplete (fs.js:99:15)

browserify config required

In order to get require('react-infinite/src/react-infinite.jsx'); working, we had to add this to react-infinite/package.json:

...
  "browserify": {
    "transform": [ ["reactify", {"es6": true}] ]
  },
...

That is because this code is using JSX and es6 features, here is some more info: andreypopp/reactify#20

Will you accept a PR with this change?

Another approach would be if you generate the transpiled .js-files and add them to the node module, see e.g. https://github.com/react-bootstrap/react-bootstrap/ (vanilla .js files end up in react-bootstrap/lib which is pointed out by main in package.json).

poor scrolling when text boxes are close together

I'm using the standard settings for Infinite:

    return React.createElement(Infinite, {
        elementHeight: 100,
        containerHeight: this.state.innerHeight-this.props.verticalOffset,
        infiniteLoadBeginBottomOffset: 200,
        handleScroll: this.handleScroll,
        onInfiniteLoad: this.handleInfiniteLoad,
        loadingSpinnerDelegate: this.elementInfiniteLoad(),
        isInfiniteLoading: this.state.isInfiniteLoading,
        timeScrollStateLastsForAfterUserScrolls: 1000,
        className: "scroller"
        }, elements);

however,I encounter several scrolling issues when the text boxes (which are referencing the CSS well class) are less than 15px apart::

.well {
    /*These two lines cause issues!*/
    margin-top:5px;
    margin-bottom:5px;

    position: center;
    margin-left:3%;
    margin-right:1%;
    width: 90%;
    background: #191919 !important;
}

the issue is that if I quickly scroll across a few hundred text boxes, the bottom half of the screen doesn't properly render. If I then scroll over it, and "flick up", then the boxes magically reappear.

This problem disappears when I increase the spacing for margin-top / margin-bottom.

Any ideas?

dynamic containerHeight?

How would I dynamically set the containerHeight in this:

    return React.createElement(Infinite, {
            elementHeight: 100,
            containerHeight: 1200,
            infiniteLoadBeginBottomOffset: 200,
            handleScroll: this.handleScroll,
            onInfiniteLoad: this.handleInfiniteLoad,
            loadingSpinnerDelegate: this.elementInfiniteLoad(),
            isInfiniteLoading: this.state.isInfiniteLoading,
            timeScrollStateLastsForAfterUserScrolls: 1000,
            className: "scroller"
            }, elements);

I would like to set it based on the page size

scrolling isn't hardware accelerated due to hooking onScroll event

To address this we can't hook the onScroll event. I think we could poll the scroll state in a timeout, or on requestAnimationFrame or every 100ms or something. Just need to configure a wide-enough visible range, so 100ms of scrolling doesn't go past the visible elements. I may be wrong, I haven't given this enough thought yet.

I can feel the difference removing the onScroll hook on my 2014 macbook pro in chrome canary - things feel snappier and slightly less clicky. The effect is minor - I never noticed the degraded perf before.

`getTopSpacerHeight` is incorrectly computing the div height

It seems that consistently, the getTopSpacerHeight is not calculating the top spacer height at the boundary:

  var previous = displayIndexStart - 1;
  return previous < 0 ? 0 : this.prefixHeightData[previous];

Not sure if this is an off by one error when getting the index of the prefixHeightData or if the height data is just not calculated correctly to begin with.

I have a list of 45 <li> elements, all of equal height [53, 53, 53...] and a scrollHeight of 993, both set on the Infinite component. Each <li> has a number denoting it's sequential position. ie <li>1</li><li>2</li>... When I scroll the components at the boundary of calculating this height, the numbers skip an <li> and start one after this position, which is completely wrong and destroys the impression of a smooth scroll. In other words, if at the top of the scrollable container, I see the <li> with the number 25 say, as soon as the bottom of that <li> element I see the like with the number 23 instead of 24, at the very top of the scrollable div.

reactify should be a dependency

Browserify transforms should be dependences rather than devDependencies so that they don't have to be installed by the parent module

Shows loading spinner even when isInfiniteLoading is set to false

When you reach to the end of the page, you see the spinner spinner element even when isInfiniteLoading is set to false. It does not go away until you manually trigger a prop change on the value passed in to the isInfiniteLoading prop.

<Infinite elementHeight={70}
containerHeight={containerHeight}
infiniteLoadBeginBottomOffset={5}
onInfiniteLoad={this.props.loadMoreLikers}
loadingSpinnerDelegate={this.elementInfiniteLoad()}
isInfiniteLoading={false}

The above code will show the spinner element when you scroll to the end of page.

Issue when trying to click

I've tried to add a click handler to a react infinite element, but the event is not getting triggered

var ListItem = React.createClass({displayName: 'ListItem',
        render: function() {
          return React.DOM.div({className: "infinite-list-item"},
          "List Item ", this.props.key
          );
        },
        handleClick: function() {
          console.log('Clicked');
        }
      });

The message is never logged to the console despite the scrolling end.

Initial Async Data

Hey,

I'm trying to get this to work in my project, but I'm running into the following problem:

  • getInitialState returns a sample list of length 1
  • when my real data is loaded asynchronously it updates the state and rerenders, but the list will only show 1 element instead of filling it with elements as specified. (Yes this is dependent on the length of the initial list).
  • Using an empty list in getInitialState does not work either as that results in an undefined is not a function error

Further Tooling Improvements

  • Set up an actual watch function
  • Split Travis tests into Jest, Flow, and ESLint
  • Create a task to be run before publishing that runs tests and builds files
  • Perhaps look into actual browser testing

Why not calculate all state variable in `componentWillReceiveProps`

in function componentWillReceiveProps,

componentWillReceiveProps(nextProps) {
    var that = this,
        newStateObject = {};

    // TODO: more efficient elementHeight change detection
    newStateObject.infiniteComputer = this.createInfiniteComputer(
                                        nextProps.elementHeight,
                                        nextProps.children
                                      );

    if (nextProps.isInfiniteLoading !== undefined) {
      newStateObject.isInfiniteLoading = nextProps.isInfiniteLoading;
    }

    var nextPBS = nextProps.preloadBatchSize;
    newStateObject.preloadBatchSize = nextPBS ? nextPBS : nextProps.containerHeight / 2;

    var nextPAH = nextProps.preloadAdditionalHeight;
    newStateObject.preloadAdditionalHeight = nextPAH ? nextPAH : nextProps.containerHeight;

    this.setState(newStateObject, () => {
      that.setStateFromScrollTop(that.getScrollTop());
    });
  },

in the last few lines, it update the state with a call back, which will update other state variable like displayIndexStart and displayIndexEnd. Why not just calculate these variable in componentWillReceiveProps ?

Best,
Jimmy

Issue when hitting the end.

Hello,
I am having an issue where I cannot seem to handle hitting the end of the elements very well. I am hitting a backend api where there is a large but limited number of results. What is the best way to do this?
Thanks!

Warning message "Iterable.length has been deprecated, use iterable.size or iterable.count()" when using ImmutableJS list as items

There is following warning. Where React.createClass.getInitialState has been called for Infinite.getInitialState() for the line "numberOfChildren: this.props.children.length,". Looks like it was caused by using ImmutableJS list as items for react-infinite component.

iterable.length has been deprecated, use iterable.size or iterable.count(). This warning will become a silent error in a future version. Error
at List.Object.defineProperty.get (http://localhost:8000/dist/bundle.js:15254:21)
at React.createClass.getInitialState (http://localhost:8000/dist/bundle.js:29042:44)
at new Constructor (http://localhost:8000/dist/bundle.js:41561:54)
at ReactCompositeComponentMixin.mountComponent (http://localhost:8000/dist/bundle.js:42085:16)
at wrapper as mountComponent
at Object.ReactReconciler.mountComponent (http://localhost:8000/dist/bundle.js:50114:35)
at Object.__REACT_INSPECTOR_RUNTIME__0_13_0.React.ReactReconciler.mountComponent (:106:41)
at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (http://localhost:8000/dist/bundle.js:48734:44)
at ReactDOMComponent.Mixin._createContentMarkup (http://localhost:8000/dist/bundle.js:43492:32)
at ReactDOMComponent.Mixin.mountComponent (http://localhost:8000/dist/bundle.js:43402:12)

Support for tables

When implementing react-infinite for trs on a table, I get some issues. Is it possible to use react-infinite for tables?

My markup is approximately set up like this:

<table>
  <tbody>
    <Infinite
      onInfiniteLoad={@paginateErrors}
      loadingSpinnerDelegate={@elementInfiniteLoad()}
      isInfiniteLoading={@state.errors.paginating}
      elementHeight={40}
      containerHeight={250}
      infiniteLoadBeginBottomOffset={200}>

      {@state.errors.map (error) =>
        <tr>
          <td>
            <div>
              <input type="checkbox" onChange={@onChange} checked={@isSelected()} />
              {@props.error.status} - {@props.error.id}
            </div>
          </td>
        </tr>
      }

    </Infinite>
  </tbody>
</table>

I get the error message:
"Uncaught Error: Invariant Violation: findComponentRoot(..., .rp2kounw1s.1.1.0.1.0.0.0.0.1:$54d55d0f6377e4eee752eada.0.0.0): Unable to find element. This probably means the DOM was unexpectedly mutated (e.g., by the browser), usually due to forgetting a when using tables, nesting tags like

,

, or , or using non-SVG elements in an parent. Try inspecting the child nodes of the element with React ID ."

It's very possible I'm going about this in the wrong way - thoughts?

Will this work within a table?

So, I ran into this nice library when looking for a way to pull this off (http://jsfiddle.net/vjeux/KbWJ2/9/), credit goes to Facebook's Vjeux for that fiddle. I was really hoping to use this in a table to dynamically load from the server infinitely without any UI lag. Alas, it does not seem to play nice with tables.

I looked at the examples provide (which are awesome and simple by the way) and I naively attempted to do this real quick just to get a feel for what is possible, praying it would work just to see if it would handle tables OK. Unfortunately this didn't work. I don't think I am doing something fundamentally wrong. Any help or advice would be greatly appreciated. Regardless, thanks for your hard work.

var ListItem = React.createClass({
    getDefaultProps: function() {
        return {
            height: 50,
            lineHeight: "50px"
        }
    },
    render: function() {
        return  (<tr>
                    <td>
                        List Item {this.props.index}
                    </td>
                </tr>);
    }
});

/// Code straight from the example with the render function slightly altered to make a table

var InfiniteList = React.createClass({
    getInitialState: function() {
        return {
            elements: this.buildElements(0, 50),
            isInfiniteLoading: false
        }
    },

    buildElements: function(start, end) {
        var elements = [];
        for (var i = start; i < end; i++) {
            elements.push(<ListItem key={i} index={i}/>)
        }
        return elements;
    },

    handleInfiniteLoad: function() {
        var that = this;
        this.setState({
            isInfiniteLoading: true
        });
        setTimeout(function() {
            var elemLength = that.state.elements.length,
                newElements = that.buildElements(elemLength, elemLength + 100000);
            that.setState({
                isInfiniteLoading: false,
                elements: that.state.elements.concat(newElements)
            });
        }, 200);
    },

    elementInfiniteLoad: function() {
        return <div className="infinite-list-item">
            Loading...
        </div>;
    },

    render: function() {
        return (<table>
                <Infinite elementHeight={50}
                         containerHeight={1000}
                         infiniteLoadBeginBottomOffset={200}
                         onInfiniteLoad={this.handleInfiniteLoad}
                         loadingSpinnerDelegate={this.elementInfiniteLoad()}
                         isInfiniteLoading={this.state.isInfiniteLoading}
                         timeScrollStateLastsForAfterUserScrolls={1000}
                         >
                    {this.state.elements}
                </Infinite>
                </table>);
    }
});

React.render(<InfiniteList/>,
        document.getElementById('infinite-example-one'));

Add support for Flexbox layouts

If you have elements side by side, the entire react-infinite just dies.

I'm guessing this is due to the height calculation, but I couldn't figure out how to extend the infinite_computer.js to get a different calculation going. Could you provide an example?

e.g: using the list from your example on: http://chairnerd.seatgeek.com/react-infinite-a-browser-ready-efficient-scrolling-container-based-on-uitableview/, all of my .infinite-list-item have .infinite-list-item { display:flex; } - The actual infinite div would have #react-example-one > div { height:250px;overflow-x:hidden;overflow-y:scroll;display:flex;flex-wrap:wrap; }

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.