1.0.4 • Published 9 months ago
react-virtual-list-sunsetiklovers v1.0.4
react-virtual-list-sunsetik
A highly performant virtualized list component for rendering large datasets efficiently in React. This library provides both horizontal and vertical virtualization to improve rendering performance by only displaying visible items.
Features
- Horizontal and Vertical Virtualization: Efficiently render large lists or grids by only rendering visible items.
- Dynamic Size Support: Handle dynamic row and column sizes based on content.
- Responsive: Automatically adjusts to the size of the container.
Installation
To use react-virtual-list-sunsetik
, install it via npm:
npm install react-virtual-list-sunsetik
Vertical scroll Usage Here's a simple example of using the library to create a virtualized list:
import React from "react";
import { useDynamicSizeGrid } from 'react-virtual-list-sunsetiklovers'
import {
useCallback,
useRef,
useState,
} from "react";
const containerHeight = 600;
const gridSize = 100
const createItems = () =>
Array.from({ length: gridSize }, () => ({
id: Math.random().toString(36).slice(2),
text: Math.random().toString(36).slice(2),
}));
export function Grid() {
const [listItems, setListItems] = useState(createItems);
const scrollElementRef = useRef<HTMLDivElement>(null);
const { virtualRows, totalHeight, measureRowHeight } = useDynamicSizeGrid({
estimateColumnWidth: useCallback(() => 16, []),
rowHeight: useCallback(() => 16, []),
rowsCount: listItems.length,
getScrollElement: useCallback(() => scrollElementRef.current, []),
getRowKey: useCallback((index) => listItems[index]!.id, [listItems]),
columnsCount: 0,
getColumnKey: useCallback((index) => index, []),
});
return (
<div style={{ padding: "0 12px" }}>
<h1>List</h1>
<div style={{ marginBottom: 12 }}>
<button
onClick={() => setListItems((items) => items.slice().reverse())}
>
reverse
</button>
</div>
<div
ref={scrollElementRef}
style={{
height: containerHeight,
overflow: "auto",
border: "1px solid lightgrey",
position: "relative",
}}
>
<div style={{ height: totalHeight }}>
{virtualRows.map((virtualItem) => {
const item = listItems[virtualItem.index]!;
return (
<div
key={item.id}
data-row-index={virtualItem.index}
ref={measureRowHeight}
style={{
position: "absolute",
top: 0,
transform: `translateY(${virtualItem.offsetTop}px)`,
padding: "6px 12px",
}}
>
{virtualItem.index} {item.id}
</div>
);
})}
</div>
</div>
</div>
);
}
Grid Usage For a grid layout, you can use the following example:
import { useDynamicSizeGrid } from 'react-virtual-list-sunsetiklovers';
import { useCallback, useRef, useState } from "react";
const containerHeight = 600;
const gridSize = 100;
const createItems = () =>
Array.from({ length: gridSize }, (_) => ({
id: Math.random().toString(36).slice(2),
columns: Array.from({ length: gridSize }, () => ({
id: Math.random().toString(36).slice(2),
text: 'You can paste a faker',
})),
}));
export function Grid() {
const [gridItems, setGridItems] = useState(createItems);
const scrollElementRef = useRef<HTMLDivElement>(null);
const {
virtualRows,
totalHeight,
measureColumnWidth,
totalWidth,
virtualColumns,
} = useDynamicSizeGrid({
rowHeight: useCallback(() => 30, []),
rowsCount: gridSize,
columnsCount: gridSize,
estimateColumnWidth: useCallback(() => 100, []),
getColumnKey: useCallback((index) => index, []),
getScrollElement: useCallback(() => scrollElementRef.current, []),
getRowKey: useCallback((index) => gridItems[index].id, [gridItems]),
});
const reverseGrid = () => {
setGridItems((items) =>
items.map((item) => ({
...item,
columns: item.columns.slice().reverse(),
})).reverse()
);
};
return (
<div style={{ padding: "0 12px" }}>
<h1>Grid</h1>
<div style={{ marginBottom: 12 }}>
<button onClick={reverseGrid}>Reverse</button>
</div>
<div
ref={scrollElementRef}
style={{
height: containerHeight,
overflow: "auto",
border: "1px solid lightgrey",
position: "relative",
}}
>
<div style={{ height: totalHeight, width: totalWidth }}>
{virtualRows.map((virtualRow) => {
const item = gridItems[virtualRow.index]!;
return (
<div
key={item.id}
style={{
position: "absolute",
top: 0,
transform: `translateY(${virtualRow.offsetTop}px)`,
padding: "6px 12px",
height: virtualRow.height,
}}
>
{virtualColumns.map((virtualColumn) => {
const item = gridItems[virtualRow.index]?.columns[virtualColumn.index];
return (
<div
data-row-index={virtualRow.index}
data-column-index={virtualColumn.index}
ref={measureColumnWidth}
style={{
position: "absolute",
left: virtualColumn.offsetLeft,
whiteSpace: "nowrap",
}}
key={virtualColumn.key}
>
{item?.text}
</div>
);
})}
</div>
);
})}
</div>
</div>
</div>
);
}
Props
UseDynamicSizeGridProps
- rowsCount: Number - The total number of rows in the grid.
- rowHeight: Function - A function that returns the height of each row.
- estimateRowHeight: Function - A function that provides an estimated height for rows.
- getRowKey: Function - A function that returns a unique key for each row.
- columnsCount: Number - The total number of columns in the grid.
- columnWidth: Function - A function that returns the width of each column.
- estimateColumnWidth: Function - A function that provides an estimated width for columns.
- getColumnKey: Function - A function that returns a unique key for each column.
- overscanY: Number - The number of additional rows to render outside the visible area (default: 3).
- overscanX: Number - The number of additional columns to render outside the visible area (default: 1).
- scrollingDelay: Number - The delay before scrolling is considered ended (default: 150 ms).
- getScrollElement: Function - A function that returns the scrollable element.