Why I built this:
I was working on a trading dashboard that needed to display 500k+ rows of live tick data. react-window worked fine at 10k rows, but at scale, every scroll event caused visible jank. Profiling showed the bottleneck was JavaScript - calculating visible ranges and item offsets was blocking the main thread for 8-12ms on each scroll.
I wondered: what if the math happened in WASM instead?
What it does:
Warper is a React hook (useVirtualizer) that renders only visible items. The difference from existing libraries:
Scroll position to visible range calculations happen in Rust/WASM Item offsets stored in a Fenwick tree for O(log n) updates when heights change Binary search for scroll-to-index is O(log n) instead of O(n) No JS object allocations during scroll = no GC pauses Technical details:
The WASM module maintains a Fenwick tree (binary indexed tree) of item heights. When you scroll:
JS passes scroll position to WASM WASM binary searches the tree to find the start index WASM returns [startIndex, endIndex, offsets[]] React renders only those items For variable heights, updating a single item's height is O(log n) instead of recalculating all subsequent offsets.
Benchmarks (Chrome, M1 Mac):
10k items: react-window 60 FPS, Warper 120 FPS 100k items: react-window ~40 FPS, Warper 120 FPS 1M items: react-window ~12 FPS, Warper 118 FPS At 10M items, react-window crashes. Warper holds at ~115 FPS.
Try it:
Live demos (no signup): https://warper.tech Stress test with 1M rows: https://warper.tech/one-million-rows Variable height chat: https://warper.tech/chat
GitHub: https://github.com/warper-org/warper npm: npm install @itsmeadarsh/warper (~45KB gzipped with WASM)
Limitations:
Requires top-level await or a bundler plugin for WASM Only React 18+ (uses useSyncExternalStore under the hood) Horizontal virtualization not yet implemented Happy to answer questions about the Fenwick tree implementation or WASM/JS interop challenges.