How to implement a paging solution using RxJs?

What is the best way to implement a paging solution in RxJs?

If want to have an observable that emits new data based on an event (could be a click, or a JavaScript function call). For instance if I have an Observable retrieving data from a Web API, and I don't want it to just keep on hammering away HTTP requests, I only want that to happen on an event triggered by the subscriber. Scenarios could be infinite scrolls (event triggered by scrolling), classic paging (event triggered by user clicking on next page) etc.

Upvotes: 1

Views: 597

Answers (1)

This is the solution I came up with based on the comments and using RxJs 6.3.3

export default class Test extends React.Component<any, any> {

  private subscription: Subscription;

  public componentDidMount() {
    const client = new MyClient();
    let source = client.get('/data');

    const buttonNotifier = defer(() => {
      console.log("waiting");
      return fromEventPattern(
        (handler) => { this.next = handler; }
      ).pipe(tap(() =>
        console.log("sending more data")
      ));
    });

    const pagedData: Observable<{Value:any, NextLink:string}> = source.pipe(
      expand(({ NextLink }) => NextLink ?
      buttonNotifier.pipe(take(1), concatMap(() => client.get(NextLink))) :
      empty()));

    this.subscription = pagedData.subscribe(
      result => {
          this.setState({
          Value: result.Value,
        });
      },
      error => {
        this.setState({
          Error: `ERROR: ${error}`
        });
      },
      () => {
        this.setState({
          Done: `DONE`
        });
      }
    );
  }

  public componentWillUnmount() {
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  }

  private next: Function;

  public render(): React.ReactElement<any> {
    return (<button onClick={()=> {this.next();}}>Next</button>);
  }
}

Upvotes: 1

Related Questions