0

我正在使用材质 UI 表和反应表的混合体。当表中的行数超过 ~200 行时,性能就不那么好了。所以我试图在开始时显示固定数量的行(假设 20 行),每当我向下滚动时,都会触发一个回调,将行附加到现有行。我正在使用 react-waypoint 启动回调,但无法弄清楚如何将行附加到当前列表的末尾。这是我的表格组件。

export default function TmpTable(props) {
  let data = props.rows;
  let columns = props.columns;
  const {getTableProps,getTableBodyProps,headerGroups,rows,prepareRow,} = useTable({columns,data,});
  let slicedRows= [];
  //considering only few rows
  slicedRows = rows.slice(0, 10);

  return (
    <TableContainer style={{ maxHeight: "350px" }}>
      <Table size="small" stickyHeader>
        <TableHead>
          {headerGroups.map((headerGroup) => (
            <TableRow {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map((column) => (
                <TableCell
                  key={column.id}
                  id={"columns" + column.Header}
                >
                  <span>{column.render("Header")}</span>
                </TableCell>
              ))}
            </TableRow>
          ))}
        </TableHead>
        <TableBody {...getTableBodyProps()}>
          {slicedRows.map((row, i) => {
            prepareRow(row);
            return (
              <>
              <TableRow {...row.getRowProps()} style={{ height: "35px" }}>
                {row.cells.map((cell) => {
                  return (
                    <TableCell {...cell.getCellProps()}>
                      {cell.render("Cell")}
                    </TableCell>
                  );
                })}
              </TableRow>
              <Waypoint onEnter={() => console.log('need to add a callback that adds more rows')}/>
              </>
            );
          })}
        </TableBody>
      </Table>
    </TableContainer>
  );
}

我知道 react-window 可以虚拟化行,但我已经创建了一个复杂的表,其中包含扩展行、行选择复选框等,并且向其中添加虚拟化似乎是不可能的。所以我认为我唯一的选择是在我上面提供的示例表代码中按需附加更多行。我不能使用钩子来存储它,slicedRows因为它会重新渲染整个组件并且我必须从头开始滚动。那么有没有办法使用 Waypoint 按需追加行?如果没有,任何人都可以建议任何其他替代方案来按需向 DOM 添加行吗?

4

1 回答 1

0

不完全是手头问题的答案,但重新渲染可能是不可避免的。您可以尝试通过记忆单元来减轻性能损失(以下示例使用lodashand React.memo):

const compareAccessors = (accessors, prevRow, nextRow) => (
  accessors.map((index) => (
    isEqual(get(prevRow, index, null), get(nextRow, index, null))
  )).reduce((last, next) => last && next, true)
);

const Cell = memo((cellData) => {
  const {
    cell,
    index,
  } = cellData;
  const tableCell = <Table.Cell key={index} {...cell.getCellProps()}>{cell.render('Cell')}</Table.Cell>;
  return tableCell;
}, (prevprops, nextprops) => {
  if (!nextprops.cell.column.accessors) {
    // simple comparison of single cell accessor
    return prevprops.cell.value == nextprops.cell.value;
  }
  // more complex comparison of accessors array on the cell.
  return compareAccessors(
    nextprops.cell.column.accessors,
    prevprops.cell.row.original,
    nextprops.cell.row.original,
  );
});

使用如下:

const columns =[
  {
    Header: 'Id',
    accessor: 'id',
  },
  {
    Header: 'Two Values',
    accessor: 'id',
    accessors: ['id', 'name'],
    Cell: ({row: { original: { id, name }}}) => (
      <div>${id}-${name}</div>
    )
  },
]

你可以更进一步,也可以记住你的行,但我在这里不包括示例代码。

于 2020-09-14T17:12:48.963 回答