gregnb / mui-datatables

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

Persist table: manually shown columns don't remain visible after refresh #1924

Open GuyShaanan opened 2 years ago

GuyShaanan commented 2 years ago
  1. Use storageKey to persist the table state.
  2. Have 1 column with display: 'false' (in the repo: the 'title' column)
  3. use the "viewColumns" to add that column to view
  4. refresh the page

Expected Behavior

  1. The column that we marked to view should remain in view after refresh

Current Behavior

  1. The column that we marked to view doesn't remain in view after refresh
  2. Hiding columns does work, they are not returned to view after refresh

Steps to Reproduce (for bugs)

https://codesandbox.io/s/muidatatables-persist-table-bug-kcrqyu

columns = [
 ...
 { name: 'Title', options: { display: 'false' } },
 ...
]

options = {
 ...
 storageKey: 'some-key'
 ...
}

Your Environment

Tech Version
Material-UI 5.x
MUI-datatables 4.1.0 (also 3.8.0)
React 17.0.2
browser *

With very shallow reading of the source code, it seems like setTableData always passes props.columns instead of checking this.state.columns, which holds the stored state.

+ const columnsToUse = this.state.columns || props.columns;
let { columns, filterData, filterList, columnOrder } = this.buildColumns(
- props.columns,
+ columnsToUse,
this.state.columns,

and

if (!sortOrder.direction) {
-        props.columns.forEach((column, colIndex) => {
+        columnsToUse.forEach((column, colIndex) => {

manually changing this piece of code seems making this bug fixed, but I really didn't checked more complex cases.

zamgill commented 2 years ago

I recently came across this issue too and haven't found a solution yet.

Usama-Tahir commented 1 year ago
+    const updatedColumns = props.columns?.map(propColumnObj => {
+      const { name } = propColumnObj;
+      const stateColumnObj = this.state.columns.find(columnObj => columnObj.name === name);
+      if (stateColumnObj == undefined) return propColumnObj;
+      propColumnObj['options'].display = stateColumnObj['display'];
+      return propColumnObj;
+    });
    let { columns, filterData, filterList, columnOrder } = this.buildColumns(
-     props.columns,
+     updatedColumns,
      this.state.columns,
      this.options.columnOrder,
      this.state.columnOrder,
    );

I'll try to find some time during the weekend to look at the repo and find a suitable solution. So far, this hack is working fine for me.