我正在使用react-table v8,我想增强我们的表性能,因为我们的单元格有点复杂,并且我们收到了数千个数据。因此,我认为是时候从客户端数据处理切换到服务器端了。
所以我有一些实现延迟加载的要求:
我还没有找到一个很好的例子来解释如何实现这一点。
如有任何帮助,我们将不胜感激。
我有很多问题,例如:
我应该使用react查询的无限查询吗?正如 react 表延迟加载示例中的文档所示?如您所见,在我的用例中没有下一页概念,因为它是一个巨大的长表,并且用户可以使用滚动条自由滚动。
如果用户滚动到页面末尾怎么办?我如何告诉 React Table 哪些行应该首先显示,哪些行应该在最后显示?
我应该使用 React Table 的分页选项,还是我自己实现其他东西?
因为我有很多功能需要稍后实现,例如选择、排序、过滤...我需要以正确的方式实现此功能。
有什么想法吗?
您应该向
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>
);
}