[单击行时cellRenderer中的IconButton触发

问题描述 投票:0回答:1

我创建了一个手风琴风格的网格。您可以单击左侧的箭头来扩大/减少行数。实际上,此网格在项目中的其他地方都可以正常工作,没有任何问题。但是,在这种情况下,我遇到了一个问题,即每当单击网格时,第一行中的展开按钮都会触发其onClick事件。在网格中的任何地方,即使在不同的行上,都将触发一个事件。

请帮助我理解这一点。

我尝试添加onRowClick函数,并基于此函数停止传播,但没有成功。

这是我的代码:


import React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';

import { withStyles } from '@material-ui/core/styles';
import TableCell from '@material-ui/core/TableCell';
import Paper from '@material-ui/core/Paper';
import { AutoSizer, Column, Table } from 'react-virtualized';
import IconButton from '@material-ui/core/IconButton';
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
import CheckIcon from '@material-ui/icons/Check';
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';

const styles = theme => ({
  flexContainer: {
    display: 'flex',
    alignItems: 'center',
    boxSizing: 'border-box',
  },
  tableRow: {
    cursor: 'pointer',
  },
  tableRowHover: {
    '&:hover': {
      backgroundColor: theme.palette.grey[200],
    },
  },
  tableCell: {
    flex: 1,
  },
  noClick: {
    cursor: 'initial',
  },
  button: {
    "&:hover": {
      backgroundColor: "transparent"
    }
  }
});


class MuiVirtualizedTable extends React.PureComponent {
  static defaultProps = {
    headerHeight: 48,
    rowHeight: 48,
  };

  getRowClassName = ({ index }) => {
    const { classes } = this.props;

    return clsx(classes.tableRow, classes.flexContainer, {
      [classes.tableRowHover]: false
    });
  };

  cellRenderer = (props) => {
    const { cellData, columnIndex } = props;
    const { columns, classes, rowHeight } = this.props;
    const style = props.rowData.child ? { height: rowHeight, backgroundColor: "#E8E8E8" } : { height: rowHeight, paddingLeft: 8, paddingRight: 4 }

    let isChild = props.rowData.child;
    let isExpanded = props.rowData.open;

    if (props.dataKey === "open") {
      return (
        <TableCell
          component="div"
          className={clsx(classes.tableCell, classes.flexContainer, {
            [classes.noClick]: false
          })}
          variant="body"
          style={style}
          align={(columnIndex != null && columns[columnIndex].numeric) || false ? 'right' : 'left'}
        >
          {
            isChild ?
              <div></div> :
              <IconButton onClick={(event) => this.props.expand(props.rowData)} className={classes.button}>
                {
                  isExpanded ? <KeyboardArrowDownIcon style={{ fontSize: 24 }} /> : <ChevronRightIcon style={{ fontSize: 24 }}></ChevronRightIcon>
                }
              </IconButton>
          }
        </TableCell>)
    }
    else if (props.dataKey === "select") {
      return (
        <TableCell
          component="div"
          className={clsx(classes.tableCell, classes.flexContainer, {
            [classes.noClick]: false
          })}
          variant="body"
          style={style}
          align={(columnIndex != null && columns[columnIndex].numeric) || false ? 'right' : 'left'}
        >
          {
            isChild ?
              <div></div> :
              <IconButton onClick={() => this.props.rowSelected(props.rowData)} className={classes.button}>
                <CheckIcon fontSize="inherit" style={{ color: "#D71920" }} />
              </IconButton>
          }
        </TableCell>)
    }

    else {
      return (
        <TableCell
          component="div"
          className={clsx(classes.tableCell, classes.flexContainer, {
            [classes.noClick]: true
          })}
          variant="body"
          style={style}
          align={(columnIndex != null && columns[columnIndex].numeric) || false ? 'right' : 'left'}
        >
          {cellData}
        </TableCell>
      );
    }
  };

  headerRenderer = ({ label, columnIndex }) => {
    const { headerHeight, columns, classes } = this.props;
    const textStyle = { color: "#D71920", fontSize: 14, fontWeight: 600 };

    return (
      <TableCell
        component="div"
        className={clsx(classes.tableCell, classes.flexContainer, classes.noClick)}
        variant="head"
        style={{ height: headerHeight, paddingLeft: 8 }}
        align={columns[columnIndex].numeric || false ? 'right' : 'left'}
      >
        <span style={textStyle}>{label}</span>
      </TableCell>
    );
  };

  render() {
    const { classes, columns, rowHeight, headerHeight, key, ...tableProps } = this.props;
    return (
      <AutoSizer>
        {({ height, width }) => (
          <Table
            key={key}
            height={height}
            width={width}
            rowHeight={rowHeight}
            headerHeight={headerHeight}
            {...tableProps}
            rowClassName={this.getRowClassName}
          >
            {columns.map(({ dataKey, ...other }, index) => {
              return (
                <Column
                  key={dataKey}
                  headerRenderer={headerProps =>
                    this.headerRenderer({
                      ...headerProps,
                      columnIndex: index,
                    })
                  }
                  className={classes.flexContainer}
                  cellRenderer={this.cellRenderer}
                  dataKey={dataKey}
                  {...other}
                />
              );
            })}
          </Table>
        )}
      </AutoSizer>
    );
  }
}

MuiVirtualizedTable.propTypes = {
  classes: PropTypes.object.isRequired,
  columns: PropTypes.arrayOf(
    PropTypes.shape({
      dataKey: PropTypes.string.isRequired,
      label: PropTypes.string.isRequired,
      numeric: PropTypes.bool,
      width: PropTypes.number.isRequired,
    }),
  ).isRequired,
  headerHeight: PropTypes.number,
  onRowClick: PropTypes.func,
  rowHeight: PropTypes.number,
};

const VirtualizedTable = withStyles(styles)(MuiVirtualizedTable);

// ---

export default function OrderGroupGrid(props) {
  const [rows, setRows] = React.useState({ data: [] });

  const expRow = (data) => {
    console.log("onSelectExpandRow: ", data)
    let row = rows.data.find(e => e.id === data.id);
    row.open = !row.open;

    let newRows = []

    if (row.open) {
      rows.data.forEach(r => {
        if (r.id !== row.id) {
          newRows.push(r);
        }
        else {
          newRows.push(r);
          r.items.forEach(child => {
            child.parentId = r.id
            child.child = true;
            newRows.push(child);
          })
        }
      })
    }
    else {
      newRows = rows.data.filter(r => r.parentId !== row.id);
    }

    setRows({ data: newRows });
  }

  const selectRow = (row) => {
    console.log("Selected Order Group: ", row)
    props.selectOrderGroup(row)
  }

  const rowClick = (e) => {
    console.log("rowClick - ", e.event);
    if (e && e.event && e.event.stopPropagation) {
      e.event.stopPropagation();
    }
  }

  if (rows.data.length === 0 && props.rows) {
    let newData = props.rows.map(r => {
      r.open = false;
      r.itemNumber = r.items.length + " items"
      return r;
    })
    setRows({ data: newData });
  }

  const columns = [
    { width: 40, maxWidth: 40, label: '', dataKey: 'open', flexGrow: 1 },
    { width: 200, label: 'Order Group Description', dataKey: 'description', flexGrow: 1 },
    { width: 100, label: 'Item Number', dataKey: 'itemNumber', flexGrow: 1 },
    { width: 200, label: 'Item Description', dataKey: 'itemDescription', flexGrow: 1 },
    { width: 60, label: '', dataKey: 'select', flexGrow: 1 }
  ]

  let rowCount = (rows && rows.data) ? rows.data.length : 0

  return (
    <React.Fragment>
      <Paper style={{ height: "35vh", width: '100%' }}>
        <VirtualizedTable
          rowCount={rowCount}
          rowGetter={({ index }) => rows.data[index]}
          columns={columns}
          expand={expRow}
          rowSelected={selectRow}
          onRowClick={rowClick}
        />
      </Paper>
    </React.Fragment>

  );
}

版本:

“反应”:“ ^ 16.9.0”“反应虚拟化”:“ ^ 9.21.1”

reactjs react-virtualized
1个回答
0
投票

问题已解决。

是在父母那里。我犯了将这个组件放置在网格容器而不是网格项中的错误。结果(据我所知)是第一个onClick事件已绑定到容器。这就是为什么我每次在网格(即容器)中单击时,都会打开或关闭第一行(也只有第一行)。

多么奇怪。

© www.soinside.com 2019 - 2024. All rights reserved.