使用延迟加载来反应表格,最初显示整个表格高度

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

我正在使用react-table v8,我想增强我们的表性能,因为我们的单元格有点复杂,并且我们收到了数千个数据。因此,我认为是时候从客户端数据处理切换到服务器端了。

所以我有一些实现延迟加载的要求:

  • 首先,它必须是延迟加载而不是分页,因为我们的应用程序中没有页面的概念
  • 我们需要在用户向下滚动时获取数据
  • 表格高度最初应该显示,没有“加载更多”按钮或加载文本。
  • 用户应该能够使用鼠标或键盘在表格中自由导航。例如,按“结束”按钮应滚动到最新数据。 (不是显示的行)

Example

我还没有找到一个很好的例子来解释如何实现这一点。

如有任何帮助,我们将不胜感激。

我有很多问题,例如:

我应该使用react查询的无限查询吗?正如 react 表延迟加载示例中的文档所示?如您所见,在我的用例中没有下一页概念,因为它是一个巨大的长表,并且用户可以使用滚动条自由滚动。

如果用户滚动到页面末尾怎么办?我如何告诉 React Table 哪些行应该首先显示,哪些行应该在最后显示?

我应该使用 React Table 的分页选项,还是我自己实现其他东西?

因为我有很多功能需要稍后实现,例如选择、排序、过滤...我需要以正确的方式实现此功能。

有什么想法吗?

javascript reactjs react-table
1个回答
0
投票

您应该向

windowing
介绍自己。

总体思路是您想要在视口中显示行的完整内容。或者,如果您想保留 Ctrl+F 功能,则仅在视口外显示单元格的浅层文本表示形式。根据经验,请记住,显示的 DOM 节点越少,性能就越好。

伪代码示例:

const { from, to } = useRowsBatchRenderer(bodyRef);

return (
  <>
    {rows.map((row) =>
      row.index < from || row.index > to ? (
        // if row is out of viewport, only render its text representation, without wrapping with CPU-expensive DOM nodes
        <ShallowGridRow
          key={row.index}
          row={row}
          height={getRowHeight(row.index) ?? minRowHeight} // For smooth scroll experience, you may also want to remember the rendered row height. If row is nit yet rendered, and height is unknown, set it to some static value
        />
      ) : (
        <GridRow key={row.index} row={row} />
      )
    )}
  </>
);

export function useRowsBatchRenderer(body: RefObject<HTMLTableSectionElement>) {
  const [rowIndicesToRender, setRowIndicesToRender] = useState<Extremes>({
    from: 0,
    to: 0,
  });

  const calculateRowIndicesToRender = useCallback(() => {
    const { scrollY, innerHeight } = window;
    // Placeholder for your custom implementation. Calculate basing on window dimensions, and table body measurements 
    setRowIndicesToRender({from: 0, to: 10});
  }, []);

  useEffect(() => {
    const throttledRerender = throttle(
      (_: Event) => calculateRowIndicesToRender(),
      50
    );

    window.addEventListener("resize", throttledRerender);
    window.addEventListener("scroll", throttledRerender);

    return () => {
      throttledRerender.cancel();
      window.removeEventListener("resize", throttledRerender);
      window.removeEventListener("scroll", throttledRerender);
    };
  }, [calculateRowIndicesToRender]);

  return rowIndicesToRender;
}

export function ShallowGridRow<D>({ height, row }: ShallowRowProps<D>) {
  // `shallowData` - delimit values with special character of your choice, NOT a white space
// NOTE: single cell per row, the less DOM nodes the better
  return (
    <tr style={{ height, overflow: "hidden", color: "transparent", wordBreak: "break-word" }}>
      <td>{row.shallowData}</td>
    </tr>
  );
}

export function GridRow<D>({ row }: RowProps<D>) {
  return (
    <tr>
      {visibleColumns.map((column) => (
        <td key={column.id}>
          <VERY_EXPENSIVE_CELL_RENDERER row={row} />
        </td>
      ))}
    </tr>
  );
}
© www.soinside.com 2019 - 2024. All rights reserved.