JSPM

  • Created
  • Published
  • Downloads 10332
  • Score
    100M100P100Q133928F
  • License MIT

A tiny React hook for rendering large datasets like a breeze.

Package Exports

  • react-cool-virtual

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (react-cool-virtual) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

🚧 Work in progress, don't use it now.



♻️
react-cool-virtual


A tiny React hook for rendering large datasets like a breeze.

npm version npm downloads npm bundle size All Contributors

Features

Motivation

When rendering a large set of data (e.g. list, table etc.) in React, we all face performance/memory troubles. There're some great libraries already available but most of them are component-based solutions that provide defined usage and increase a lot of bundle size. However a library comes out as a hook-based solution. It more flexible but applying styles for using it can be verbose. Furthermore, it lacks some of the useful features.

React Cool Virtual is a tiny React hook that gives you a better DX and modern way for virtualizing a large amount of data without struggle 🤯.

Getting Started

To use React Cool Virtual, you must use react@16.8.0 or greater which includes hooks.

Installation

This package is distributed via npm.

$ yarn add react-cool-virtual
# or
$ npm install --save react-cool-virtual

⚠️ This package using ResizeObserver API under the hook. Most modern browsers support it natively, you can also add polyfill for full browser support.

CDN

If you're not using a module bundler or package manager. We also provide a UMD build which is available over the unpkg.com CDN. Simply use a <script> tag to add it after React CND links as below:

<script crossorigin src="https://unpkg.com/react/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom/umd/react-dom.production.min.js"></script>
<!-- react-cool-virtual comes here -->
<script crossorigin src="https://unpkg.com/react-cool-virtual/dist/index.umd.production.min.js"></script>

Once you've added this you will have access to the window.ReactCoolVirtual.useVirtual variable.

Basic Usage

Here's the basic concept of how it rocks:

import useVirtual from "react-cool-virtual";

const List = () => {
  const { outerRef, innerRef, items } = useVirtual({
    itemCount: 10000, // Provide the total number for the list items
    itemSize: 50, // The size of each item (default = 50)
  });

  return (
    <div
      ref={outerRef} // Set the scroll container with the `outerRef`
      style={{ width: "300px", height: "500px", overflow: "auto" }}
    >
      {/* Set the inner element with the `innerRef` */}
      <div ref={innerRef}>
        {items.map(({ index, size }) => (
          // You can set the item's height with the `size` property
          <div key={index} style={{ height: `${size}px` }}>
            Row {index}
          </div>
        ))}
      </div>
    </div>
  );
};

✨ Pretty easy right? React Cool Virtual is more powerful than you think. Let's explore more use cases through the examples!

Examples

Some of the common use cases that React Cool Virtual can help you out.

Fixed Size

This example demonstrates how to create a fixed size row. For column or grid, please refer to CodeSandbox.

Edit RCV - Fixed Size

import useVirtual from "react-cool-virtual";

const List = () => {
  const { outerRef, innerRef, items } = useVirtual({
    itemCount: 1000,
  });

  return (
    <div
      className="outer"
      style={{ width: "300px", height: "300px", overflow: "auto" }}
      ref={outerRef}
    >
      <div ref={innerRef}>
        {items.map(({ index, size }) => (
          <div key={index} style={{ height: `${size}px` }}>
            ♻️ {index}
          </div>
        ))}
      </div>
    </div>
  );
};

Variable Size

This example demonstrates how to create a variable size row. For column or grid, please refer to CodeSandbox.

Edit RCV - Variable Size

import useVirtual from "react-cool-virtual";

const List = () => {
  const { outerRef, innerRef, items } = useVirtual({
    itemCount: 1000,
    itemSize: (idx) => (idx % 2 ? 100 : 50),
  });

  return (
    <div
      className="outer"
      style={{ width: "300px", height: "300px", overflow: "auto" }}
      ref={outerRef}
    >
      <div ref={innerRef}>
        {items.map(({ index, size }) => (
          <div key={index} style={{ height: `${size}px` }}>
            ♻️ {index}
          </div>
        ))}
      </div>
    </div>
  );
};

Dynamic Size

This example demonstrates how to create a dynamic size row. For column or grid, please refer to CodeSandbox.

Edit RCV - Dynamic Size

import useVirtual from "react-cool-virtual";

const List = () => {
  const { outerRef, innerRef, items } = useVirtual({
    itemCount: 1000,
    itemSize: 75, // The unmeasured item sizes will refer to this value (default = 50)
  });

  return (
    <div
      className="outer"
      style={{ width: "300px", height: "300px", overflow: "auto" }}
      ref={outerRef}
    >
      <div ref={innerRef}>
        {items.map(({ index, measureRef }) => (
          // Use the `measureRef` to measure the item size
          <div key={index} ref={measureRef}>
            {/* Some data... */}
          </div>
        ))}
      </div>
    </div>
  );
};

💡 Jumping while scrolling? It's because the total size of the items is gradually corrected along with an item has been measured. You can tweak the itemSize to reduce the phenomenon.

Real-time Resize

This example demonstrates how to create a real-time resize row (e.g. expand/collapse). For column or grid, please refer to CodeSandbox.

// Coming soon...

Performance Optimization

Coming soon...

How to Share A ref?

You can share a ref as follows, here we take the outerRef as the example:

import { useRef } from "react";
import useVirtual from "react-cool-virtual";

const App = () => {
  const ref = useRef();
  const { outerRef } = useVirtual();

  return (
    <div
      ref={(el) => {
        outerRef.current = el; // Set the element to the `outerRef`
        ref.current = el; // Share the element for other purposes
      }}
    />
  );
};

Working in TypeScript

React Cool Virtual is built with TypeScript, you can tell the hook what type of your outer and inner elements are as follows:

import useVirtual from "react-cool-virtual";

const App = () => {
  // 1st is the `outerRef`, 2nd is the `innerRef`
  const { outerRef, innerRef } = useVirtual<HTMLDivElement, HTMLDivElement>();

  return (
    <div ref={outerRef}>
      <div ref={innerRef}>{/* Rendering items... */}</div>
    </div>
  );
};

💡 For more available types, please check it out.

API

Coming soon...

ResizeObserver Polyfill

ResizeObserver has good support amongst browsers, but it's not universal. You'll need to use polyfill for browsers that don't support it. Polyfills is something you should do consciously at the application level. Therefore React Cool Virtual doesn't include it.

We recommend using @juggle/resize-observer:

$ yarn add @juggle/resize-observer
# or
$ npm install --save @juggle/resize-observer

Then pollute the window object:

import { ResizeObserver } from "@juggle/resize-observer";

if (!("ResizeObserver" in window)) window.ResizeObserver = ResizeObserver;

You could use dynamic imports to only load the file when the polyfill is required:

(async () => {
  if (!("ResizeObserver" in window)) {
    const module = await import("@juggle/resize-observer");
    window.ResizeObserver = module.ResizeObserver;
  }
})();

To Do...

  • Unit testing
  • Reverse scrolling
  • Infinite loop
  • scrollBy method

Contributors ✨

Thanks goes to these wonderful people (emoji key):


Welly

🤔 💻 📖 🚇 🚧

This project follows the all-contributors specification. Contributions of any kind welcome!