在 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;