A React hook for virtualizing large lists and improving performance
npm install @custom-react-hooks/use-virtualA React hook for implementing list virtualization, enabling efficient rendering of large datasets by only rendering visible items in the viewport.
- 📋 List Virtualization: Render only visible items for optimal performance
- 📏 Dynamic Heights: Support for variable item heights
- 🔄 Horizontal & Vertical: Support for both scrolling directions
- 🎯 Overscan: Configurable buffer for smoother scrolling
- 📊 Performance Metrics: Track rendering performance
- 🎣 Scroll Control: Programmatic scrolling to specific items
- 📱 Mobile Optimized: Touch-friendly scrolling
- 🧮 Memory Efficient: Minimal memory footprint for large lists
``bash`
npm install @custom-react-hooks/use-virtual
`jsx
import React from 'react';
import { useVirtual } from '@custom-react-hooks/use-virtual';
function VirtualList() {
const items = Array.from({ length: 10000 }, (_, i) => Item ${i});
const {
visibleItems,
totalHeight,
scrollToIndex,
scrollToTop
} = useVirtual({
items,
itemHeight: 50,
containerHeight: 400
});
return (
$3
`jsx
import React from 'react';
import { useVirtual } from '@custom-react-hooks/use-virtual';function DynamicHeightList() {
const items = Array.from({ length: 1000 }, (_, i) => ({
id: i,
content:
Item ${i},
height: 50 + (i % 3) * 25 // Variable heights
})); const getItemHeight = (index) => items[index].height;
const { visibleItems, totalHeight } = useVirtual({
items,
itemHeight: getItemHeight,
containerHeight: 600
});
return (
{visibleItems.map(({ item, index, style }) => (
{item.content}
))}
);
}
`$3
`jsx
import React from 'react';
import { useVirtual } from '@custom-react-hooks/use-virtual';function HorizontalList() {
const items = Array.from({ length: 1000 }, (_, i) =>
Column ${i}); const { visibleItems, totalHeight } = useVirtual({
items,
itemHeight: 200, // Width in horizontal mode
containerHeight: 800, // Container width
horizontal: true
});
return (
{visibleItems.map(({ item, index, style }) => (
{item}
))}
);
}
`$3
`jsx
import React from 'react';
import { useVirtual } from '@custom-react-hooks/use-virtual';function OptimizedList() {
const items = Array.from({ length: 50000 }, (_, i) => ({
id: i,
name:
User ${i},
email: user${i}@example.com
})); const { visibleItems, startIndex, endIndex } = useVirtual({
items,
itemHeight: 60,
containerHeight: 500,
overscan: 10, // Render 10 extra items for smoother scrolling
onScroll: ({ scrollTop, startIndex, endIndex }) => {
console.log(
Scrolled to ${scrollTop}, showing items ${startIndex}-${endIndex});
}
}); return (
Showing items {startIndex} to {endIndex} of {items.length}
{visibleItems.map(({ item, index, style }) => (
{item.name}
{item.email}
))}
);
}
`$3
`jsx
import React from 'react';
import { useVirtual } from '@custom-react-hooks/use-virtual';function VirtualGrid() {
const items = Array.from({ length: 10000 }, (_, i) =>
Cell ${i});
const itemsPerRow = 5;
const rows = Math.ceil(items.length / itemsPerRow);
const rowItems = Array.from({ length: rows }, (_, rowIndex) =>
items.slice(rowIndex itemsPerRow, (rowIndex + 1) itemsPerRow)
); const { visibleItems } = useVirtual({
items: rowItems,
itemHeight: 100,
containerHeight: 400
});
return (
{visibleItems.map(({ item: rowItems, index, style }) => (
{rowItems.map((item, cellIndex) => (
key={cellIndex}
style={{
flex: 1,
border: '1px solid #ccc',
padding: 10,
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
>
{item}
))}
))}
API Reference
$3
`typescript
interface VirtualOptions {
items: T[];
itemHeight: number | ((index: number) => number);
containerHeight: number;
overscan?: number;
horizontal?: boolean;
onScroll?: (info: ScrollInfo) => void;
}
`$3
`typescript
interface VirtualState {
visibleItems: VirtualItem[];
totalHeight: number;
startIndex: number;
endIndex: number;
scrollToIndex: (index: number) => void;
scrollToTop: () => void;
}
`#### Properties
- visibleItems (
VirtualItem): Array of visible items with positioning
- totalHeight (number): Total height of all items
- startIndex (number): Index of first visible item
- endIndex (number): Index of last visible item
- scrollToIndex (function): Scroll to specific item index
- scrollToTop (function): Scroll to the top of the list#### VirtualItem
`typescript
interface VirtualItem {
item: T;
index: number;
style: React.CSSProperties;
}
`Use Cases
1. Large Data Tables: Efficiently render thousands of rows
2. Chat Applications: Handle long message histories
3. Product Catalogs: Display large inventories
4. Social Media Feeds: Infinite scrolling feeds
5. File Explorers: Navigate large directory structures
6. Data Visualization: Render large datasets
7. Mobile Lists: Optimize performance on mobile devices
Performance Benefits
- Memory Efficiency: Only renders visible items
- Smooth Scrolling: Maintains 60fps even with large datasets
- Reduced DOM Nodes: Minimal DOM manipulation
- Fast Initial Load: Quick rendering regardless of data size
TypeScript Support
This hook is written in TypeScript and provides full type safety:
`typescript
import { useVirtual, VirtualOptions, VirtualState } from '@custom-react-hooks/use-virtual';interface User {
id: number;
name: string;
email: string;
}
const options: VirtualOptions = {
items: users,
itemHeight: 60,
containerHeight: 400
};
const virtual: VirtualState = useVirtual(options);
``MIT © Bane Grozdanovic