Code, Design, and Growth at SeatGeek

Jobs at SeatGeek

We are growing fast, and have lots of open positions!

Explore Career Opportunities at SeatGeek

React Infinite: A Browser-ready Efficient Scrolling Container Based on UITableView

A browser-ready efficient scrolling container based on UITableView

We’re growing more every day, adding new brokers to our comprehensive list of ticket sources, and expanding our list of event tickets. With this, and our continuing focus on cross-event search, we’re showing more ticket listings to more people than ever before.

The default DOM scrolling implementation is, unfortunately, inefficient. Tens of thousands of DOM nodes that are out of the view of the user are left in the DOM. For cross-event comparisons in particular, this quickly makes the performance of our ticket listings unacceptable.

React Infinite solves this with an approach popularized by iOS’s UITableView. Only DOM nodes that are in view or about to come into view are rendered in full. This makes scrolling performance constant throughout the length of the entire list regardless of the number of items added.

We’re using React Infinite in production on our event map pages right now; 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.

To get you started, here is an example that implements an infinite scrolling list with a simulated loading delay of 2.5 seconds:

And the code to do it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
var ListItem = React.createClass({
    render: function() {
        return <div className="infinite-list-item">
        List Item {this.props.key}
        </div>;
    }
});

var InfiniteList = React.createClass({
    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}/>)
        }
        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}
                         infiniteLoadingBeginBottomOffset={200}
                         onInfiniteLoad={this.handleInfiniteLoad}
                         loadingSpinnerDelegate={this.elementInfiniteLoad()}
                         isInfiniteLoading={this.state.isInfiniteLoading}
                         >
            {elements}
        </Infinite>;
    }
});

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

For the complete documentation, head over to the Github repo, or download it on NPM with npm install react-infinite or Bower with bower install react-infinite. We hope you’ll be able to use React Infinite in creating a better, faster, and smoother web.

Comments