Dale Navi
Dale Navi

Reputation: 66

How to render a long list in react-relay?

A lazy scrolling list component for react-web backing onto a Relay Connection, with paginated fetching, while offering good performance and memory characteristics.

Two things to manage

Is there some particular list component which handles this well? Is there an established pattern for implementing this common mechanism?

Upvotes: 2

Views: 1133

Answers (1)

Greg Hurrell
Greg Hurrell

Reputation: 5437

This pattern is pretty much the representative scenario for connections. Here's a hypothetical <PostsIndex> component that shows a list of posts with a "load more" button. If you don't want to explicitly change the UI when in the isLoading state you could delete the constructor and the setVariables callback. Adding viewport based infinite scrolling would not be hard either; you'd just need to wire a scroll listener up to you setVariables call.

class PostsIndex extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isLoading: false};
  }

  _handleLoadMore = () => {
    this.props.relay.setVariables({
      count: this.props.relay.variables.count + 10,
    }, ({ready, done, error, aborted}) => {
      this.setState({isLoading: !ready && !(done || error || aborted)});
    });
  }

  render() {
    return (
      <div>
        {
          this.props.viewer.posts.edges.map(({node}) => (
            <Post key={node.id} post={node} />
          ))
        }
        {
          this.props.viewer.posts.pageInfo.hasNextPage ?
            <LoadMoreButton
              isLoading={this.state.isLoading}
              onLoadMore={this._handleLoadMore}
            /> :
            null
        }
      </div>
    );
  }
}

export default Relay.createContainer(PostsIndex, {
  initialVariables: {
    count: 10,
  },
  fragments: {
    viewer: () => Relay.QL`
      fragment on User {
        posts(first: $count) {
          edges {
            node {
              id
              ${Post.getFragment('post')}
            }
          }
          pageInfo {
            hasNextPage
          }
        }
      }
    `,
  },
});

Upvotes: 6

Related Questions