Terra-core: Infinite Scroller Component

Created on 2 Aug 2017  路  18Comments  路  Source: cerner/terra-core

Issue Description

Create Infinite Scroller component.

Issue Type

  • [x] New Feature
  • [ ] Enhancement
  • [ ] Bug
  • [ ] Other

Expected Behavior

A component that infinitely loads content within a scrollable container that by only rendering content the user is able to see or might soon see.

Functional Review Required

Most helpful comment

@jmsv6d I like endContent, I think I will update loader to loaderContent to be consistent

All 18 comments

@emilyrohrbough does this include pagination as well, or just specifically infinite scroll?

@jordanlawrence15 This is specifically infinite scroll

Tech Design for Infinite Scroller

Summary:

The terra-infinite-scroller component is a component that infinitely loads content within a scrollable container that only renders content the user is able to see or might soon see. This component wraps the react-infinite-scroller.

React Props:

| Prop | Type | Default | Description |
|----------|------|---------|--------------|
| children | node | undefined | The items to be rendered |
| loaderContent | node | 'Loading...' | The loading content to display if content is at the end of the page and content is not fully loaded. |
| threshold | number | 250 | The distance in pixels before the end of the items that will trigger a call to loadMore. |
| responsiveTo | string | 'parent' | Wether responsive to the window, or else, the component's parentNode. Options are 'window' or 'parent' |
| loadMore | func | undefined | A callback to load more items when the indicated threshold is reached. The page number to be loaded is passed through from react-infinite-scroller. |
| hasMore | bool | false | Indicates if there are more items to be loaded |
| pageStart | number | 0 | The page number that is initially loaded. |
| initialLoad | bool | false | Indicates if the loadMore should be called immediately upon render. |
| endContent | node | 'No more items' | The content to display when to indicate the end of the loadable content is reached. |

Question

Do we want to expose the initialLoad prop to consumers? This is a prop available by react-infinite-scroller when set to true, will immediately call the loadMore function. IMO we could keep this prop internal to our component and set it as false.

Example:

import React from 'react';
import InfiniteScroller from 'terra-infinite-scroller';

let nestedComponentIndex = 5;
const initialItems = [
  <p> Element 1 </p>,
  <p> Element 2 </p>,
  <p> Element 3 </p>,
  <p> Element 4 </p>,
  <p> Element 5 </p>,
];

class InfiniteScrollerExample extends React.Component {
  constructor(props) {
    super(props);
    this.state = { items: initialItems, hasMore: true, intialLoad: true };
    this.loadMore = this.loadMore.bind(this);
  }

  loadMore(page) {
    if (page === 1) {
      this.setState({ initialLoad: false });
    }

    if (this.state.items.length < 500) {
      let i;
      const items = this.state.items;
      for (i = 0; i < 5; i += 1) {
        items.push(<p>Element {nestedComponentIndex += 1} </p>);
      }
      this.setState({ items });
    } else {
      this.setState({ hasMore: false });
    }
  }

  render() {
    const loaderContent = <div> Loading... </div>;
    const endContent = <div> End Reached! </div>;
    return (
      <div >
        <InfiniteScroller
          initialLoad={this.state.initialLoad}
          loadMore={this.loadMore}
          hasMore={this.state.hasMore}
          threshold={200}
          loader={loaderContent}
          endContent={endContent}
        >
          {this.state.items}
        </InfiniteScroller>
      </div>
    );
  }
}

CSS Classes:

| Selector | Description |
|------------------|-------------|
| .infinite-scroller | Sets the infinite scroller container style |
| .loader | Sets the loader container style |
| .end | Set the end-of-content container style |

Do we plan to change the loader based on framework, or is the 'Loading...' seen in the live demo the planned direction?

The Loading... would be provided by us since we would have to provide translations.

Per @jordanlawrence15 suggestion, adding the prop endReached to indicate the end of the loadable content is reached. I don't love the name and would love suggestions.

^Added to design above.

I think endContent, endReachedContent, or something similar would be more appropriate.

@jmsv6d I like endContent, I think I will update loader to loaderContent to be consistent

+1 for tech design

+1 on tech design

This is Nick Smith. Are you all sure that react-infinite-scroller is a "true" infinite scroller where it recycles views from the top and bottom that come out of view?

Based on looking at their demo page, it is only appending to the bottom of the page. This will eventually run into a large number of DOM elements as a user scrolls. A "true" infinite scroll component should be operating under the "adapter" or "recycled view" pattern where a callback is made to render only the views that are necessary in the scroll viewport.

@nickpith it's not a true infinite scroller. We agree that this component should not simply append to the bottom of the page and will likely have to create our own component. This will have the unfortunate side effect of pushing out the delivery date of this component.

What is the expected use case of the infinite scroller? Is it intended for lists of content where each item is a constant height? Or is it supposed to be a general purpose scroller for any kind of content that can be variable per child in the scroller?

I would assume it is desired for list type usage where the items have roughly a constant height but I was curious.

It is supposed to be a general purpose scroller for any kind of content that can be variable per child in the scroller.

In that case, I'm not sure you can ever make a general purpose infinite scroller that only renders what is in view.

Orion JIRA created

Closing until we get OCS design input

Was this page helpful?
0 / 5 - 0 ratings