gregnb / mui-datatables

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

Table sort is lost if data changed on a re-render #305

Closed joaoaguiam closed 5 years ago

joaoaguiam commented 5 years ago

If user has sorted a column and the table data changed afterwards, the table is render with the new data but the sort is not taken into account.

Expected Behavior

When the table data is updated, the re-rendering of the MUI DataTables should take into account the previously selected sort by the user.

Current Behavior

Currently, in this situation, the rows are back to the initial order and not sorted correctly. However, the column header still indicates the sort icon correctly (based on the previously clicked column).

Steps to Reproduce (for bugs)

I am storing the table data in the state and derive it from the props. If the props change, the data in the state is updated. The MUIDataTable component is retrieving the data directly from the state on the render method.

Your Environment

Tech Version
Material-UI 1.4.3
MUI-datatables 2.0.0-beta-38
React 16.5.0
Browser Chrome
hwatersiv commented 5 years ago

I have encounter this same issue. Anyone know if there is a work around until this is resolved?

cwkeller commented 5 years ago

I was using react. I created a wrapper component that would save off the state of the table and re-apply it during render. Because of a sort issue (#273) I was also sorting the table and saving that to updatedColumns. The important code is below.

const options = {
      filter: true,
      selectableRows: false,
      filterType: 'dropdown',
      responsive: 'stacked',
      rowsPerPage: this.state.tableState ? this.state.tableState.rowsPerPage : 10,
      onTableChange: (action, tableState) => {
        this.state.tableState = tableState;
      },
      filterList: this.state.tableState ? this.state.tableState.filterList : filterList,
    };
    return (
      <MUIDataTable
        title={title}
        data={dataSorted || data}
        columns={updatedColumns}
        options={options}
      />
    );
gregnb commented 5 years ago

This issue might be addressed with the latest version. Can anyone confirm?

gregnb commented 5 years ago

Bump. Can anyone confirm?

cwkeller commented 5 years ago

Looks like it is still doing it for me with 2.0.0 beta 48 but I could be doing something wrong.

the-noob commented 5 years ago

FWIW sorting doesn't work at all for me with updated props. I have an async action retrieving the listing and when it completes, while the table is updated, the sorting doesn't work at all. 2.0.0.beta-50 Edit In my case the issue was with customBodyRender and sorting + filtering on the same column.

joaoaguiam commented 5 years ago

For me, the version 2.0.0-beta-42 fixes the issue.

asharafshahi commented 5 years ago

I'm on 2.0.0-beta-54 and I am wrestling with this issue now. Will try the work around mentioned by cwkeller

kapalex commented 5 years ago

My take on how to deal with this issue : I created a function columns as such

const columns = (orderBy,) => {
  const columns = {...}; // base column data here
  Object.keys(orderBy).forEach(
    key => (columns[key].options.sortDirection = orderBy[key])
  );
  return Object.values(columns);
}

Each column entry is of the following format

  id: {
      label: "ID",
      name: "id",
      options: { download: false, filter: false, sort: false, display: false }
    },

Now in the render function

render() {
    const { orderBy, } = this.state;
    return (
        <MUIDataTable
          title="Hosts"
          data={...}
          columns={columns(statusMapping, actionMapping, orderBy,)}
          options={...}
        />
    );
}
gregnb commented 5 years ago

Can anyone affected by this upgrade to "2.0.0-beta.59" and let me know if this is still an issue? otherwise I will look to close

ideoclickVanessa commented 5 years ago

@gregnb While we no longer seem to experience "sort order" loss with 2.0.0-beta.59, we do still experience "rows per page" and "current page" loss.

stephan-king commented 5 years ago

I'm still experiencing sort order loss when updating the data with 2.0.0-beta.59

gabrielliwerant commented 5 years ago

I can verify that the currentPage and numberOfRows is lost after a data state change if a custom page option is provided, but I can't verify the sort order problem. @stephan-king Can you post an example of the sort order being lost?

stephan-king commented 5 years ago

In my case, data is bound to the state, and I am updating the table by updating the state. I've implemented an edit button that makes the network call when the edit form is submitted and then raises an event that in turn updates the state and triggers a refresh of the grid. The new data is there, but the sort order is lost. I'll work on a code example for you.

gabrielliwerant commented 5 years ago

Thank you @stephan-king! I have an example locally, without any network calls, that allows updates to state, but I don't see any change in the sort order after doing so, hence why I might need to see what you're doing in case there's something else happening I'm not accounting for.

kpervin commented 5 years ago

@gabrielliwerant

Still experiencing this issue on "mui-datatables": "^2.0.0". We use Meteor for reactive data, but even when child components in customBodyRender re-render, it affects the whole table and the following is lost:

This also occurs if I do a search, had filters in place, and then cancel the search; I lose all state for filters, columns, and sort direction.

gabrielliwerant commented 5 years ago

@ShaggyKris It sounds like what you are describing might be a separate issue. Can you open up a new issue with an example codepen of this not working? I could look into it then. It's hard to say at this point, but it might have something to do with the way meteor is interacting with react.

Also, be aware that these changes have not yet found their way into a new release, so the situation may be different once they do. For now, you can experiment by pulling master.

kpervin commented 5 years ago

Also, be aware that these changes have not yet found their way into a new release, so the situation may be different once they do. For now, you can experiment by pulling master.

I'll try making a sample project to test with master, but it won't be done today as I have some other obligations I need to fulfill. I'll report back.

gabrielliwerant commented 5 years ago

Closing this issue, as I was unable to verify it, and it's possible it was fixed in a new release since the issue was originally open.

kpervin commented 5 years ago

Closing this issue, as I was unable to verify it, and it's possible it was fixed in a new release since the issue was originally open.

This is not resolved. I am currently using ^2.2.0, and any state change causes the sort to be lost. I tested this by creating a button that simply toggles a bool state value, and it causes all sorting to be lost. That's not all. All settings from the table are abandoned.

However, I've done a little digging and I think it has to do with customBodyRender. I wrapped the MUIDatatable in a PureComponent class with only title, options, columns, data props and used the following code:

difference(object, base) {
    function changes(object, base) {
        return _.transform(object, function(result, value, key) {
            if (!_.isEqual(value, base[key])) {
                result[key] =
                    _.isObject(value) && _.isObject(base[key])
                        ? changes(value, base[key])
                        : value;
            }
        });
    }
    return changes(object, base);
}

componentDidUpdate(prevProps, prevState, snapshot) {
    if (this.state !== prevState){
        console.log(
            "State Difference: ",
            this.difference(this.state, prevState)
        );
    }
    if (this.props !== prevProps){
        console.log(
            "Props Difference: ",
            this.difference(this.props, prevProps)
        );
    }
}

I determined what was changing was the column values themselves. Upon further investigation, it was ONLY the columns that used customBodyRender. One of my typical customBodyRender functions are as follows:

customBodyRender: (value, tableMeta) => {
    if (
        value === "Not Registered" &&
        typeof tableMeta.rowData[0] === "object"
    ) {
        const { containerValue } = tableMeta.rowData[0];
        return (
            <Button
                onMouseOver={this.disableRowClick}
                onMouseOut={this.enableRowClick}
                onClick={() =>
                    this.resendInvite(
                        containerValue.subValue1,
                        containerValue.subValue2
                    )
                }
                variant={"contained"}
            >
                Resend
            </Button>
        );
    }
    return value;
},

However, it is even triggered on customBodyRender functions which simply return a <a> tag.

gabrielliwerant commented 5 years ago

@ShaggyKris I need to see your code in a sample project, as I cannot verify this locally. I've used existing examples and added state changing with sorting, and I do not see the issue you are referring to, which means there may be something happening that is specific to your exact situation. codesandbox is a fine place for it, and you do not need to create a new repo.

kpervin commented 5 years ago

@gabrielliwerant I found the issue. I was generating a title for the filename in the downloadOptions with the name of the table and current date. However, this caused the whole table to re-render and lose state whenever it updated. Containing the MuiDataTable in a PureComponent and setting the downloadOptions.filename there solved the issue. However, I don't think the table should lose state should the filename be updated.

gabrielliwerant commented 5 years ago

@gabrielliwerant Again, this isn't something I'm able to reproduce, so I can't resolve the issue. :( I need you to provide a specific, minimal implementation to demonstrate this breaking. You may have a lot going on in your codebase which is affecting this and I can't tell what that might be from my end.

kpervin commented 5 years ago

@gabrielliwerant

Hey there, so I have no idea what happened by apparently it seems to have resolved itself? I appreciate it regardless. I'll contact you if it seems to happen again.

gabrielliwerant commented 5 years ago

@ShaggyKris Glad it worked out! It's possible that there was a fix or code change at some point that corrected it.

Fabbok1x commented 5 years ago

Problem persists in ^2.6.4. @ShaggyKris : Could you let me know which version you are using, would be very helpful.

gabrielliwerant commented 5 years ago

Hello @Fabbok1x. Can you please open a new issue with details about what difficulties you are encountering and a minimal code example to reproduce the issue?

Fabbok1x commented 5 years ago

@gabrielliwerant : Yes. Submitted: https://github.com/gregnb/mui-datatables/issues/807

AmitJoki commented 4 years ago

@gabrielliwerant here's the codesandbox - https://codesandbox.io/s/muidatatables-custom-toolbar-29pms

I think it should be opened. When certain properties are set via state, the table state is getting lost. I am using the latest version as of writing this. Go to the codesandbox and sort on name and wait for 5 seconds to see it getting reset.

bretep commented 4 years ago

@gabrielliwerant same issue here. I’ll try to debug more tomorrow.

camba063 commented 4 years ago

Looks like some people are still having issues. I just tackled this one today. Data was lost on search or sort. It worked after second page load. I discovered that datatable initialization happened before table was fully rendered from using data from api call. I'm using hooks so documentation and help is spotty still.

Solution was to create async function to a) use await to make call to update dataset then b) init datatable. Async function was called from useEffect function to run on load. Everything is working like a charm now. Can provide code if anyone wants it.

ghost commented 4 years ago

@camba063 I would love to see your solution. I am using hooks as well.

kpalumbohp commented 9 months ago

This still seems to be an issue on the latest version. The sorting state is getting lost on each re-render