DevExpress / devextreme-reactive

Business React components for Bootstrap and Material-UI
https://devexpress.github.io/devextreme-reactive/
Other
2.08k stars 382 forks source link

Virtual Scrolling with Remote Data in Reactive Grid #1912

Closed SergeyAlexeev closed 5 years ago

SergeyAlexeev commented 5 years ago

The Problem

The current Virtual Scrolling implementation requires that all data rows are provided simultaneously. It slows down the Grid at startup and generates an excessive amount of server traffic.

The Proposed Solution

We are going to introduce a new 'VirtualTableState' plugin that manages grid rows.

The getRows property contains a function that uses the skip and take arguments to load new rows. It is called when a user scrolls the Grid to the bottom.

The start property allows you to scroll the Grid to a specific row. This row is rendered at the top of the table. Set this property to the index of the row in the entire dataset.

The rowCount property sets the total row count. The greater the rowCount, the smaller the vertical scrollbar. If the rowCount is unspecified, pages are loaded in sequence, and the scrollbar's size depends on the number of rendered rows.

To reduce the number of requests to the server, the Grid will cache a portion of loaded rows. We will also provide utilities that help you configure row caching.

In addition, the Grid makes scrolling smoother by rendering skeleton cells for rows that should be loaded.

grid-vs

class MyApp extends React.Component {
  constructor() {
    /* ... */
    this.state = {
      rows: [],
      totalCount: 0,
      start: 0
    };
  }
  getRemoteRows(skip, take) {
    const query = `https://YOUR_API/?requireTotalCount=true&skip=${skip}&take=${take}`;
    fetch(query)
      .then(response => response.json())
      .then((data) => {
          this.setState({
            rows: data.data,
            totalCount: data.totalCount,
            start: skip,
          });
      });
  }
  render() {
    const { rows, start, totalCount } = this.state;
    return (
      <Grid rows={rows}>
        <VirtualTableState
          start={start}
          rowCount={totalCount}
          getRows={this.getRemoteRows}
        />
        <VirtualTable />
      </Grid>
    );
  }
}

We Need Your Feedback

Take a Quick Poll

Do you find lazy loading in Reactive Grid useful?

Live Sandbox

Coming soon.

Get Notified of Updates

Subscribe to this thread or to our Facebook and Twitter accounts for updates on this topic.

yotamberk commented 5 years ago

Sounds awesome! Really! The only comment I have is that in my API I don't have a skip and take parameters for pagination. I allow the user to limit the number of documents the user would like and if the user requests pagination, I give him the first batch by the limit specified and an id generated in the server to the next batch of documents he can query in the future. It's a bit different than the concept introduced here. It's a bit different than the concept introduced here.

In any case, great work! Looking forward to this feature!

SergeyAlexeev commented 5 years ago

Thank you for pointing out to that. We'll take your scenario into account.

incadoi commented 5 years ago

and what about the select all checkbox, how is it going to work?

MaximKudriavtsev commented 5 years ago

We have released the @next version of DevExtreme Reactive Grid with this feature. Feel free to provide your feedback about its functionality and documentation.

A package that contains the described functionality has the next tag:

npm i --save @devexpress/dx-react-core@next @devexpress/dx-react-grid@next
npm i --save @devexpress/dx-react-grid-material-ui@next
OR
npm i --save @devexpress/dx-react-grid-bootstrap3@next
OR
npm i --save @devexpress/dx-react-grid-bootstrap4@next
MatthieuCoelho commented 5 years ago

Nice feature thanks. I tried to use it, homewer I wonder how to refresh the grid, I tried to do this

this.cache.invalidate();
this.setState({rows: [], skip: 0, loading: true, totalCount: 5000});

but then getRows isn't called by the grid, why ?

ushkal commented 5 years ago

Hi @MatthieuCoelho,   Thank you for pointing out the issue. We'll fix it soon.

ushkal commented 5 years ago

@MatthieuCoelho, we researched your scenario and concluded that this behavior is expected: the grid requests rows only on user interactions such as scrolling, changing sorting, or filtering. In your case, I suggest you manually fetch rows on refresh as follows:

this.cache.invalidate();
this.getRemoteRows(this.state.skip, VIRTUAL_PAGE_SIZE * 2);
MaximKudriavtsev commented 5 years ago

We have released the 1.11.0 version of DevExtreme Reactive Grid with this feature.

A package that contains the described functionality has the latest tag:

npm i --save @devexpress/dx-react-core @devexpress/dx-react-grid
npm i --save @devexpress/dx-react-grid-material-ui
OR
npm i --save @devexpress/dx-react-grid-bootstrap3
OR
npm i --save @devexpress/dx-react-grid-bootstrap4
lock[bot] commented 5 years ago

This thread has been automatically locked since it is closed and there has not been any recent activity. Please open a new issue for related bugs or feature requests.