gregnb / mui-datatables

Datatables for React using Material-UI
MIT License
2.71k stars 935 forks source link

Infinite Scrolling? #569

Open mikeps34 opened 5 years ago

mikeps34 commented 5 years ago

Is it possible to implement infinite scrolling? I've used a standard MUI Table component and added a Waypoint control to trigger a GET of more data. I don't see a way to accomplish this with this component.

Is it possible to do in another way?

mikeps34 commented 5 years ago

perhaps maybe a preRender function, or a way to inject an object? Here's a stripped down version of my other code. I'm new to this, so maybe I overlooked something simple. `

Id Other Column
        <TableBody>
          {dataset.map(({id, otherData}, i, item) => (
            <Fragment key={id}>
              {/* Waypoint is used for infinite scrolling, when reached, fetch more data */}
              {i === dataset.length - 10 && (
                <Waypoint onEnter={() => {
                  const newData = this.getMoreRows(50);
                  this.setState({
                    dataset: [...dataset, ...newData]
                  });
                }}
                />)
              }
              <TableRow key={id}>
                <TableCell component="th" scope="row"> {id}</TableCell>
                <TableCell component="th" scope="row"> {otherdata}</TableCell>
              </TableRow>
            </Fragment>
        </TableBody>
    </Table>

`

gabrielliwerant commented 5 years ago

Can you create a codepen https://codepen.io/ example with what you're trying to do? It should be possible to implement something like infinite scrolling in your table, but I'm not personally familiar with the Waypoint library.

mikeps34 commented 5 years ago

Let me know if this works for you: https://codesandbox.io/s/52xz76v5wn

gabrielliwerant commented 5 years ago

It looks like you're nesting the Waypoint inside of the table body, but you don't have an easy way to do the same with mui-datatables. See if you can place it outside the table and still have the events and callbacks fire so you can update the state.

If not, you can try nesting in the footer with customFooter, the toolbar with customToolbar, or finally with a column via customBodyRender.

mikeps34 commented 5 years ago

I don't think it is possible to place it outside of the table. The point of waypoint is that is fires an event when the user scrolls to that element, so it would have to be in the table itself.

Do you have any other suggestions to make your component support infinite scrolling? I'm not tied to waypoint, it is the infinite scrolling functionality that I would like to implement, regardless of how.

gabrielliwerant commented 5 years ago

Did you try placing it in the footer, toolbar, or body via the options I suggested above?

mikeps34 commented 5 years ago

My apologies. I'm a bit new to react, so part of my question is "do you think I'm implementing this properly"? I will try these, but thought maybe you had a better option in mind rather than using waypoint. Thank you.

mikeps34 commented 5 years ago

Sorry for the late reply, I got pulled off to something else for a bit... Yes, I was able to use waypoint within customBodyRender and it works perfectly. Thank you for the help!

gabrielliwerant commented 5 years ago

Glad to hear it! Would you be able to update your codepen with a working example, in case this question comes up again?

mikeps34 commented 5 years ago

Not the cleanest code, but here's the updated codepen. Thanks again for your help! https://52xz76v5wn.codesandbox.io/

venkateshzifo commented 5 years ago

Hi, Any update on this one ? I am looking for an infinite scroll example. Can someone help me ?

tomduval commented 4 years ago

This method no longer works in v3 - has anyone got a solution? Thank you!

n.b. it only works with responsive: "stacked"

patorjk commented 4 years ago

I think this may be a codesandbox issue. I initially had trouble with it working up to version 2.6.3 of mui-datatables and failing in version 2.6.4. However, this sandbox - which uses the latest version of the table - appears to work fine in Firefox:

https://codesandbox.io/s/mui-table-infinite-scroll-s05b1?file=/src/messagemanager.js

It won't load in Chrome, but I have a feeling something else is going on. If you can try it on your own box I'd recommend that. If it fails let me know.

tomduval commented 4 years ago

Thanks for the reply @patorjk

If you change responsive to "standard" then it stops working (both in codesandbox and locally). That was n.b. at the end of my last comment - sorry if that didn't make sense.

patorjk commented 4 years ago

Looks like you just need to add the tableBodyHeight parameter (otherwise in standard mode the table will use the height of the parent):

https://codesandbox.io/s/mui-table-infinite-scroll-flumc?file=/src/messagemanager.js

tomduval commented 4 years ago

Interesting... in the previous version, you didn't need to specify the height of the table. This means that you just needed to scroll the page. Now, for this to work, you need to have the table scroll independently of the page which is a bit annoying. Let me know if there is a solution to this. Thank you for your help!

patorjk commented 4 years ago

The previous responsive modes will still work, you just get a deprecation notice in the console. The tableBodyHeight was separated out from the responsive parameter because previously there was no easy way to set the table height (ex: for "scrollMaxHeight" it was hard coded at 499px). You can see the styling used for the various modes here: https://github.com/gregnb/mui-datatables/blob/master/src/MUIDataTable.js#L1713

tableBodyHeight or tableBodyMaxHeight can be any CSS string (ex: '500px', '100%', 'auto', 'none', etc).

arkhannanov commented 4 years ago

Gyes, I struggled with React Waypoint, but faced with problem onEnter fires always, so data uploading constantly without specific scroll point.

To avoid this problem you can just use VisibilitySensor from "react-visibility-sensor";

`customBodyRender: (value, tableMeta, updateValue) => { const {filteredData} = this.state; const rowIndex = tableMeta.rowIndex;

                if (rowIndex === filteredData.length - 1) {
                    return (
                        <VisibilitySensor onChange={this.onChange}>
                            <div>{value}</div>
                        </VisibilitySensor>
                    );
                } else {
                    return <Fragment>{value}</Fragment>;
                }
            }`

`onChange = async (isVisible) => {

    const {state: {filteredData}} = this;

    if (isVisible) {
        const data = await this.getNewData(
            filteredData.length
        );
        this.setState({
            filteredData: [...filteredData, ...data],
        });
    }
}

`