• Stars
    star
    1,166
  • Rank 40,051 (Top 0.8 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created about 2 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A zero-config, fast and small (~3kB) virtual list (and grid) component for React, Vue, Solid and Svelte.

virtua

npm npm bundle size npm check demo

A zero-config, fast and small (~3kB) virtual list and grid component for React.

If you want to check the difference with the alternatives right away, see comparison section.

Motivation

This project is a challenge to rethink virtualization. The goals are...

  • Zero-config virtualization: This library is designed to give the best performance without configuration. It also handles common hard things in the real world (dynamic size measurement, scroll position adjustment in bottom-up scrolling and imperative scrolling, etc).
  • Fast: Scrolling without frame drop needs optimization in many aspects (reduce CPU usage, reduce GC, reduce layout recalculation, optimize with CSS, optimize for frameworks, etc). We are trying to combine the best of them.
  • Small: Its bundle size should be small as much as possible to be friendly with modern web development. Currently each components are ~3kB gzipped and the total is ~4kB gzipped.
  • Flexible: Aiming to support many usecases - fixed size, dynamic size, horizontal scrolling, reverse scrolling, rtl direction, sticky, infinite scrolling, placeholder, scrollTo, scroll restoration, dnd, table, and more. See live demo.
  • Framework agnostic (WIP): Currently only for React but we could support Vue, Svelte, Solid, Angular, Web Components and more in the future.

Demo

https://inokawa.github.io/virtua/

Install

npm install virtua

Requirements

  • react >= 16.14

If you use ESM and webpack 5, use react >= 18 to avoid Can't resolve react/jsx-runtime error.

If you use this lib in legacy browsers which does not have ResizeObserver, you should use polyfill.

Usage

Vertical scroll

import { VList } from "virtua";

export const App = () => {
  return (
    <VList style={{ height: 800 }}>
      {Array.from({ length: 1000 }).map((_, i) => (
        <div
          key={i}
          style={{
            height: Math.floor(Math.random() * 10) * 10 + 10,
            borderBottom: "solid 1px gray",
            background: "white",
          }}
        >
          {i}
        </div>
      ))}
    </VList>
  );
};

Horizontal scroll

import { VList } from "virtua";

export const App = () => {
  return (
    <VList style={{ height: 400 }} horizontal>
      {Array.from({ length: 1000 }).map((_, i) => (
        <div
          key={i}
          style={{
            width: Math.floor(Math.random() * 10) * 10 + 10,
            borderRight: "solid 1px gray",
            background: "white",
          }}
        >
          {i}
        </div>
      ))}
    </VList>
  );
};

Vertical and horizontal scroll

import { VGrid } from "virtua";

export const App = () => {
  return (
    <VGrid style={{ height: 800 }} row={1000} col={500}>
      {({ rowIndex, colIndex }) => (
        <div
          style={{
            width: ((colIndex % 3) + 1) * 100,
            border: "solid 1px gray",
            background: "white",
          }}
        >
          {rowIndex} / {colIndex}
        </div>
      )}
    </VGrid>
  );
};

Window scroll

import { WVList } from "virtua";

export const App = () => {
  return (
    <div style={{ padding: 200 }}>
      <WVList>
        {Array.from({ length: 1000 }).map((_, i) => (
          <div
            key={i}
            style={{
              height: Math.floor(Math.random() * 10) * 10 + 10,
              borderBottom: "solid 1px gray",
              background: "white",
            }}
          >
            {i}
          </div>
        ))}
      </WVList>
    </div>
  );
};

React Server Components (RSC) support

This library is marked as a Client Component. You can render RSC as children of VList or WVList.

// page.tsx in App Router of Next.js

export default async () => {
  const articles = await fetchArticles();
  return (
    <div>
      <div>This is Server Component</div>
      <VList style={{ height: 300 }}>
        {articles.map((a) => (
          <div key={a.id} style={{ border: "solid 1px gray", height: 80 }}>
            {a.content}
          </div>
        ))}
      </VList>
    </div>
  );
};

And see examples for more usages.

Documentation

Comparison

Features

virtua react-virtuoso react-window react-virtualized @tanstack/react-virtual react-cool-virtual
Bundle size 4.7kB gzipped 16.3kB gzipped 6.4kB gzipped 27.3kB gzipped 2.3kB gzipped 3.1kB gzipped
Vertical scroll 🟠 (needs customization) 🟠 (needs customization)
Horizontal scroll 🟠 (needs customization) 🟠 (needs customization)
Grid (Virtualization for two dimension) (VGrid) ✅ (FixedSizeGrid / VariableSizeGrid) ✅ (Grid) 🟠 (needs customization) 🟠 (needs customization)
Table 🟠 (needs customization) (TableVirtuoso) 🟠 (needs customization) (Table) 🟠 (needs customization) 🟠 (needs customization)
Window scroller (WVList) (WindowScroller)
Dynamic list size 🟠 (needs AutoSizer) 🟠 (needs AutoSizer)
Dynamic item size 🟠 (needs additional codes and has wrong destination when scrolling to item imperatively) 🟠 (needs CellMeasurer and has wrong destination when scrolling to item imperatively) 🟠 (has wrong destination when scrolling to item imperatively) 🟠 (has wrong destination when scrolling to item imperatively)
Reverse scroll
Reverse scroll in iOS Safari
Infinite scroll 🟠 (needs react-window-infinite-loader) 🟠 (needs InfiniteLoader)
Bi-directional infinite scroll 🟠 (has startItem method but its scroll position can be inaccurate)
Scroll restoration (getState)
Smooth scroll
RTL direction
SSR support
React Server Components (RSC) support ? ? ? (hook) (hook)
Display exceeding browser's max element size limit
  • ✅ - Built-in supported
  • 🟠 - Supported but partial, limited or requires some user custom code
  • - Not officially supported

Benchmarks

WIP

Basically by design, this library uses children instead of render prop like other virtual scrollers. It reduces rerender during scrolling with caching element instances. However it may make component's mount slower if you display million items.

Contribute

All contributions are welcome. If you find a problem, feel free to create an issue or a PR.

Making a Pull Request

  1. Clone this repo.
  2. Run npm install.
  3. Commit your fix.
  4. Make a PR and confirm all the CI checks passed.

More Repositories

1

rich-textarea

A small customizable textarea for React to colorize, highlight, decorate texts, offer autocomplete and much more.
TypeScript
296
star
2

react-native-react-bridge

An easy way to integrate your React (or Preact/React Native Web) app into React Native app with WebView.
TypeScript
253
star
3

remark-slate-transformer

remark plugin to transform remark syntax tree (mdast) to Slate document tree, and vice versa. Made for WYSIWYG markdown editor.
TypeScript
105
star
4

react-native-wasm

A polyfill to use WebAssembly in React Native.
Kotlin
83
star
5

lang-box

💻 Update a pinned gist to contain languages of your recent commits in GitHub
JavaScript
52
star
6

react-animatable

Tiny(~1kB) animation hooks for React, built on Web Animations API.
TypeScript
38
star
7

remark-docx

remark plugin to compile markdown to docx (Microsoft Word, Office Open XML).
TypeScript
33
star
8

rust-editor

An implementation of text editor with Rust/WebAssembly.
Rust
25
star
9

remark-pdf

remark plugin to compile markdown to pdf.
TypeScript
24
star
10

react-use-d3

A small React hook to use D3 in declarative way, for data visualization & flexible animation.
TypeScript
7
star
11

remark-extract-toc

remark plugin to store table of contents
JavaScript
6
star
12

react-reconciler-practice

A practice with react-reconciler.
TypeScript
4
star
13

monaco-diff

Text diff library exported from monaco-editor-core, which is core of VS Code.
TypeScript
4
star
14

dotparser-normalized

A wrapper of dotparser to parse GraphViz dot file and collect nodes / edges.
TypeScript
3
star
15

react-typescript-example

Sandbox for React and TypeScript
TypeScript
3
star
16

wasm-ts-runtime

[WIP]A toy WebAssembly runtime implementation with TypeScript.
TypeScript
2
star
17

inokawa.github.io

GitHub Pages
TypeScript
2
star
18

rust-browser

A toy browser engine implementation with Rust.
Rust
2
star
19

react-native-with-web-example

A setup of React Native with React Native Web.
Java
2
star
20

apollo-graphql-practice

JavaScript
1
star
21

node-bundler

A toy JavaScript bundler with Node.js.
JavaScript
1
star
22

react-grpc-web

[WIP] Typed React hooks for gRPC-web.
TypeScript
1
star
23

tweened

A simple, declarative and composable animation library for React.
TypeScript
1
star
24

webgl-practice

WebGL sandbox
TypeScript
1
star
25

reagram

React component to render customizable graph/diagram.
TypeScript
1
star
26

arduino-sketches

Sandbox for Arduino
C++
1
star
27

rust-wasm-example

Some examples of WebAssembly generated by Rust.
Rust
1
star
28

d3-sandbox

D3.js Practice
JavaScript
1
star
29

monaco-editor-node

Wrapper of monaco-editor to use some functionalities in Node.js.
JavaScript
1
star
30

react-native-accelerate

Java
1
star
31

babel-plugin-evaluate-modules

A babel plugin to evaluate modules at build-time.
TypeScript
1
star
32

web3d-sandbox

WebGL/WebGPU/GLSL Practice
JavaScript
1
star
33

canvas-game

A toy 2D shooting game built on pure Canvas API.
TypeScript
1
star
34

webgl-mdn-practice

JavaScript
1
star
35

webgpu-practice

WebGPU sandbox
TypeScript
1
star