Blueprint: ColumnHeaderCell menuRenderer triggers for every column on click and shows a warning

Created on 20 Mar 2018  路  1Comment  路  Source: palantir/blueprint

Bug report

Package version(s): 2.0.0-rc.3
Browser and OS versions: Chrome 65.0.3325.162, OSX 10.13.2

Steps to reproduce

import React from "react";
import {
  Cell,
  Column,
  Table,
  SelectionModes,
  ColumnHeaderCell,
} from "@blueprintjs/table";
import { Menu, MenuItem } from "@blueprintjs/core";

const sampleData = [
  {id: "test1", group: "Sample group", data1: 88, data2: 79, data3: "7.48"},
  {id: "test2", group: "Sample group", data1: 58, data2: 75, data3: "10.49"},
  {id: "test3", group: "Sample group", data1: 10, data2: 68, data3: "0.89"},
  {id: "test4", group: "Sample group", data1: 3, data2: 51, data3: "5.70"},
  {id: "test5", group: "Sample group", data1: 3, data2: 0, data3: "5.83"}
];

class SampleTable extends React.Component {
  renderColumns = () => {
    const columns = [];

    Object.keys(sampleData[0]).forEach(columnname => {
      const menuRenderer = columnIndex => {
//=>>>>>this is the main problem
        console.info("menuRenderer triggered for ", columnIndex);
//<<<<<<<<<====
        return (
          <Menu>
            <MenuItem icon="sort-asc" text="Sort Asc" />
            <MenuItem icon="sort-desc" text="Sort Desc" />
          </Menu>
        );
      };

      const columnHeaderCellRenderer = () => (
        <ColumnHeaderCell name={columnname} menuRenderer={menuRenderer}/>
      );

      columns.push(
        <Column
          key={columnname}
          name={columnname}
          columnHeaderCellRenderer={columnHeaderCellRenderer}
          cellRenderer={this.renderCell}
        />
      );
    });

    return columns;
  };

  renderCell = (rowIndex, columnIndex) => {  // eslint-disable-line
    const rowData = sampleData[rowIndex];
    const keyNameOfCurrentColumn = Object.keys(rowData)[columnIndex];
    const valueOfCurrentColumn = rowData[keyNameOfCurrentColumn];

    return <Cell>{valueOfCurrentColumn}</Cell>; // eslint-disable-line
  };

  render() {
    return <Table numRows={sampleData.length}
                  selectionModes={SelectionModes.ROWS_AND_CELLS}
    >{this.renderColumns()}</Table>;
  }
}

export default SampleTable;

Actual behavior

Left-clicking on a ColumnHeader leads to EVERY column triggered and menu is not drawn.
Output on a left-click from the example above:

menuRenderer triggered for  0
menuRenderer triggered for  1
menuRenderer triggered for  2
menuRenderer triggered for  3
menuRenderer triggered for  4

Left-clicking on a ColumnHeader menu icon triggers EVERY column menuRenderer TWO TIMES and the correct column menu is drawn.
For example left-clicking on column 2 menu icon:

menuRenderer triggered for  0
menuRenderer triggered for  1
menuRenderer triggered for  2
menuRenderer triggered for  3
menuRenderer triggered for  4
menuRenderer triggered for  0
menuRenderer triggered for  1
menuRenderer triggered for  2
menuRenderer triggered for  3
menuRenderer triggered for  4
menuRenderer triggered for  2

Right-click on a ColumnHeader triggers the only column and a menu is drawn. Right-click on a ColumnHeader for the first time after the page loads leads to a warning:

Warning: Each child in an array or iterator should have a unique "key" prop.

Check the render method of Blueprint2.Overlay. See https://fb.me/react-warning-keys for more information.
in CSSTransition (created by Blueprint2.Overlay)
in Blueprint2.Overlay (created by Blueprint2.Popover)
in span (created by Manager)
in Manager (created by Blueprint2.Popover)
in Blueprint2.Popover (created by ContextMenu)
in div (created by ContextMenu)
in ContextMenu

Expected behavior

Only the column clicked is triggered(with a different behaviour) depending on left-click/right-click.

ps
I ran into this in a case when I needed to sort asc<->desc on a left-click(single tap) on a column without showing any menu, and show a custom Menu on right-click(tap and hold). Still can't figure it out.

Most helpful comment

I don't know... Definitely Menu renderer triggers with page load - its normal. But then it recalls with every click.
Most likely it's normal behaviour.
But the thing I don't like - I don't see a direct way to separate RIGHT-click on column header with LEFT-click. There's no "onClick" event on ColumnHeaderCell.
So I had to use a construction

        <span onClick={leftClick}><ColumnHeaderCell
          menuRenderer={menuRenderer}
        /></span>

>All comments

I don't know... Definitely Menu renderer triggers with page load - its normal. But then it recalls with every click.
Most likely it's normal behaviour.
But the thing I don't like - I don't see a direct way to separate RIGHT-click on column header with LEFT-click. There's no "onClick" event on ColumnHeaderCell.
So I had to use a construction

        <span onClick={leftClick}><ColumnHeaderCell
          menuRenderer={menuRenderer}
        /></span>
Was this page helpful?
0 / 5 - 0 ratings

Related issues

brsanthu picture brsanthu  路  3Comments

vinz243 picture vinz243  路  3Comments

ernestofreyreg picture ernestofreyreg  路  3Comments

adidahiya picture adidahiya  路  3Comments

raiju picture raiju  路  3Comments