1.0.4 • Published 9 months ago

react-virtual-list-sunsetiklovers v1.0.4

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

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.
1.0.4

9 months ago

1.0.3

9 months ago

1.0.2

9 months ago

1.0.1

9 months ago

1.0.0

9 months ago