3

在 React Virtualized Infinite Loader 上实现过滤器。每次应用过滤器时,过滤后的数据都会附加到已经渲染的行,而不是在表中渲染过滤后的数据。还使用上下文 API 来获得共同的事实来源。但基本上虚拟化表不会被清除。那么有什么更好的方法来解决它?React 和 Infinite Loader 的新手。分享代码:

Parent Component:-
import React from 'react';
import { Paper } from '@material-ui/core';
import { withApollo, compose } from 'react-apollo';
import CustomizedVirtualizedTable from '../../CustomizedVirtualizedTable';
import { WithContext } from '../../../HOCmiddleware/withcontext';

const rows = [];

const pushDataInRow = props => {
  let botsList = props && props.value.botsDataList.list;

  if (botsList) {
    for (let i = 0; i < botsList.length; i++) {
      let el = botsList[i];
      if (rows.indexOf(el) === -1) {
        rows.push(el);
      }
    }
  }
};
const isRowLoaded = ({ index }) => {
  return !!rows[index];
};

const headCells = [
  {
    dataKey: 'BotId',
    label: 'Bot ID',
    width: '150'
  },
  { dataKey: 'Status', numeric: false, label: 'Status', width: '150' },
  {
    dataKey: 'CurrentTask',
    label: 'Current Task',
    width: '150'
  },
  {
    dataKey: 'ChargeStatus',
    label: 'Charge Status',
    width: '150'
  },
  {
    dataKey: 'OperatingTime',
    disablePadding: false,
    label: 'Operating Time',
    width: '150'
  }
];

const VirtualizedBotsTable = props => {

  const totalDataCount = props.data.TotalBotCount;
  pushDataInRow(props);
  return (
    <Paper
      style={{
        height: 500,
        width: '100%',
        paddingLeft: '20px',
        boxSizing: 'border-box'
      }}
    >
      <CustomizedVirtualizedTable
        rowCount={rows.length}
        totalDataCount={totalDataCount}
        rowGetter={({ index }) => rows[index]}
        fetchDataQuery={props.fetchDataQuery}
        columns={headCells}
        isRowLoaded={isRowLoaded}
      />
    </Paper>
  );
};

export default compose(withApollo)(WithContext(VirtualizedBotsTable));


Child Component:-
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, InfiniteLoader } from 'react-virtualized';
import { PAGE_LIMIT_SIZE } from '../constants/frontEndConstants';

const styles = theme => ({
  flexContainer: {
    display: 'flex',
    alignItems: 'center',
    boxSizing: 'border-box'
  },
  table: {
    // temporary right-to-left patch, waiting for
    // https://github.com/bvaughn/react-virtualized/issues/454
    '& .ReactVirtualized__Table__headerRow': {
      flip: false,
      paddingRight: theme.direction === 'rtl' ? '0px !important' : undefined
    }
  },
  tableRow: {
    cursor: 'pointer'
  },
  tableRowHover: {
    '&:hover': {
      backgroundColor: theme.palette.grey[200]
    }
  },
  tableCell: {
    flex: 1
  },
  noClick: {
    cursor: 'initial'
  }
});

class MuiVirtualizedTable extends React.PureComponent {
  static defaultProps = {
    headerHeight: 48,
    rowHeight: 48
  };
  constructor(props) {
    super();
    this.state = {
      totalDataCount: 0
    };
  }

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

    return clsx(classes.tableRow, classes.flexContainer, {
      [classes.tableRowHover]: index !== -1 && onRowClick != null
    });
  };

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

  isRowLoaded = ({ index }) => {
    return !!this.state.loadedData[index];
  };

  headerRenderer = ({ label, columnIndex }) => {
    const { headerHeight, columns, classes } = this.props;

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

  render() {
    const {
      classes,
      columns,
      rowHeight,
      headerHeight,
      totalDataCount,
      ...tableProps
    } = this.props;
    return (
      <InfiniteLoader
        isRowLoaded={this.props.isRowLoaded}
        loadMoreRows={this.props.fetchDataQuery}
        rowCount={totalDataCount}
        threshold={10}
      >
        {({ onRowsRendered, registerChild }) => (
          <AutoSizer>
            {({ height, width }) => (
              <Table
                height={height}
                width={width}
                rowHeight={rowHeight}
                gridStyle={{
                  direction: 'inherit'
                }}
                headerHeight={headerHeight}
                className={classes.table}
                {...tableProps}
                rowClassName={this.getRowClassName}
                ref={registerChild}
                onRowsRendered={onRowsRendered}
              >
                {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>
        )}
      </InfiniteLoader>
    );
  }
}

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 CustomizedVirtualizedTable = withStyles(styles)(MuiVirtualizedTable);
export default CustomizedVirtualizedTable;
4

0 回答 0