React-data-grid: How to force update grid columns

Created on 22 Mar 2017  路  15Comments  路  Source: adazzle/react-data-grid

Hi,

I have the grid with two columns "Column A" & "Column B".
I setstate and change the columns to "Column B" & "Column A".

But the grid didn't refresh and the columns are still "Column A" & Column B"

wontfix

Most helpful comment

In case someone hit similar situation as me, I note down my simple solution here for record purpose.

My columns are built dynamically, so I just simply add an unique property (e.g. hash) to every column element, it works for me. Sample on codesandbox

  buildColumns = columns =>
    columns.map((col, i) => ({
      ...col,
      hash: (new Date).getTime() // <---------
    }));

I guess the problem caused by HeaderRow.js' shouldComponentUpdate, a hash make whole columns different for every build.

  shouldComponentUpdate(nextProps) {
    return (
      nextProps.width !== this.props.width
      || nextProps.height !== this.props.height
      || nextProps.columns !== this.props.columns // <---------------
      || !shallowEqual(nextProps.style, this.props.style)
      || this.props.sortColumn !== nextProps.sortColumn
      || this.props.sortDirection !== nextProps.sortDirection
    );
  }

Hope it helps.

All 15 comments

@happyheartman Hi, same is happening to me, I have to do this.setState({ columns: []}) and then this.setState({ columns: [ column A, column B ,....]}), not the best solution I know, but it helped me...

@martinnov92 What I did is add extra " " character to the name of one column and the grid columns will updates. So i;m alternating " " & "" when setState(columns) . Seems like the grid is checking object changes to update the grid for performance.

I too had a similar situation. I had to update the width of the columns so that the column gets expanded when the rows are rendered. I used slice() to create a new reference to the columns variables and then changed the state. Something like

let updatedColumns = myOldColumns.slice();
// modified updatedColumns
this.setState({
     columns: updatedColumns
})

Hope it helps

I was having a similar situation with updating grid data en masse, and found this helpful: https://github.com/adazzle/react-data-grid/issues/332

The issue is, that the detection of the column change is broken. It only checks if the columns in the previous column list do exist in the new list, which is true, but it does not check, if they are in the same order, so it does not re-render. Also going forward to React 16+, the double setState wont even work, as they will be merged into one setState.

The compareEachColumn function needs to be fixed to check for the order as well, not just existence, which IMO would result in a shorter and cleaner code as well.

I just opened an PR to fix this issue thanks to @Poetro suggestion.

Found a workaround, see my comment here https://github.com/adazzle/react-data-grid/issues/197#issuecomment-384084671

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Please reopen this if you feel it has been incorrectly closed and we will do our best to look into it. Thank you for your contributions.

grid.setColumnTitle(index.'nameIwant'); is also not working guys !!!

None of the suggestions above are working. I'm trying to add a column based on user input, so they can add/remove columns to display on the fly. The rows data underneath already has all columns present, I just don't have the room to display all 20 columns.

https://fancygrid.com/api/methods/hidecolumn
have you tried this ??
If not set a Boolean variable to the hidden attribute and try by reloading the grid after the user input has been taken !!!
Which framework are you working with ??
Lemme know more

In case someone hit similar situation as me, I note down my simple solution here for record purpose.

My columns are built dynamically, so I just simply add an unique property (e.g. hash) to every column element, it works for me. Sample on codesandbox

  buildColumns = columns =>
    columns.map((col, i) => ({
      ...col,
      hash: (new Date).getTime() // <---------
    }));

I guess the problem caused by HeaderRow.js' shouldComponentUpdate, a hash make whole columns different for every build.

  shouldComponentUpdate(nextProps) {
    return (
      nextProps.width !== this.props.width
      || nextProps.height !== this.props.height
      || nextProps.columns !== this.props.columns // <---------------
      || !shallowEqual(nextProps.style, this.props.style)
      || this.props.sortColumn !== nextProps.sortColumn
      || this.props.sortDirection !== nextProps.sortDirection
    );
  }

Hope it helps.

Thank you @neotan you are a god send!!

@patwalls u r welcome =)

@neotan
Actually you don't need to change all the columns.
Only one column need to be changed, and it can change from false to true and vice versa.

Let's assume we have in state columns:

columns: [
      {
        key: "id",
        name: "ID",
        width: 50,
        draggable: true,
        unusedProperty: false, // <--- add some property and set to false
      },
      {
        key: "title",
        name: "Title",
        draggable: true,
        resizable: true,
      },
      {
        key: "count",
        name: "Count",
        draggable: true,
        resizable: true,
      }
    ],
onHeaderDrop = (source, target) => {
    let columns = [...this.state.columns];
    const columnSourceIndex = columns.findIndex(i => i.key === source);
    const columnTargetIndex = columns.findIndex(i => i.key === target);
    const temp = { ...columns[columnSourceIndex] };
    columns[columnSourceIndex] = { ...columns[columnTargetIndex] };
    columns[columnTargetIndex] = temp;

    //NEW code
    //lets change only column with key "id"
    const IndexOfIdColumn = columns.findIndex(i => i.key === "id");
    let IdColumn = { ...columns[IndexOfIdColumn] };
    IdColumn.unusedProperty = !IdColumn.unusedProperty; //<--change from true to false and vice versa
    columns[IndexOfIdColumn] = IdColumn;
    //END of new code
    this.setState({ columns });
  };

This code also works.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

markmus picture markmus  路  4Comments

jmahony picture jmahony  路  4Comments

ryanwtyler picture ryanwtyler  路  3Comments

alvaro1728 picture alvaro1728  路  4Comments

anil1712 picture anil1712  路  4Comments