npm package: @jason12306/react-async-virtual-scroll
Description: High-performance asynchronous virtual scroll component for react with dynamic height support and optimized rendering for large datasets
Author: Jason12306
Latest version: 1.0.0

# async-virtual-scroll - React Asynchronous Virtual Scroll Component

> High-performance virtual scroll component supporting dynamic height rendering, optimized for large data list display

[简体中文](https://github.com/Jason12306/react-async-virtual-scroll/blob/main/README-ZH_CN.md)

[vue Version](https://github.com/Jason12306/vue-async-virtual-scroll)

## Features

- 🚀 Efficient rendering of massive data
- 📏 Supports fixed height and dynamic height
- 🔍 Automatically calculates visible area content
- 🔄 Built-in scroll optimization and buffer mechanism
- ⏳ Smart loading state management
- 🔧 Highly customizable

## Installation & Usage

### Installation

```bash
npm install @jason12306/react-async-virtual-scroll
```

### Basic Usage

```tsx
import React, { useState } from 'react'
import AsyncVirtualScroll from '@jason12306/react-async-virtual-scroll'
import '@jason12306/react-async-virtual-scroll/react-async-virtual-scroll.css'

const App = () => {
  const [enabled, setEnabled] = useState(true)
  const items = Array.from({ length: 500 }, (_, i) => ({
    id: i + 1,
    text: `Item ${i + 1}`,
    color: (i + 1) % 2 ? '#e0f7fa' : '#fffde7',
  }))

  return (
    <div style={{ height: 500, border: '1px solid #ddd', overflow: 'auto' }}>
      <AsyncVirtualScroll
        value={enabled}
        data={items}
        itemSize={60}
        keyField="id"
      >
        {(item, index, dataUid) => (
          <div
            key={item.id}
            data-uid={dataUid}
            style={{
              height: 60,
              lineHeight: '60px',
              padding: '0 16px',
              borderBottom: '1px solid #eee',
              backgroundColor: item.color,
              boxSizing: 'border-box',
            }}
          >
            {item.id}. {item.text}
          </div>
        )}
      </AsyncVirtualScroll>
    </div>
  )
}

export default App
```

## Props Configuration

| Name        | Type             | Required                    | Default    | Description                                                       |
| ----------- | ---------------- | --------------------------- | ---------- | ----------------------------------------------------------------- |
| value       | Boolean          | Yes                         | false      | Controls whether virtual scroll is enabled (controlled mode)      |
| ban         | Boolean          | No                          | false      | Disables virtual scroll (suitable for small datasets)             |
| itemSize    | Number           | Required for fixed height   | undefined  | Item height in fixed height mode (px)                             |
| minItemSize | Number           | Required for dynamic height | undefined  | Minimum item height in dynamic height mode (px)                   |
| data        | Array            | Yes                         | []         | Data array to render                                              |
| buffer      | [number, number] | No                          | [200, 200] | Buffer size [top buffer, bottom buffer] (px)                      |
| keyField    | String           | No                          | 'id'       | Unique identifier field name for data items                       |
| dataUid     | String           | No                          | 'data-uid' | DOM attribute name for storing unique data identifier             |
| viewNum     | Number           | No                          | 1          | Initial minimum visible item count (for estimation)               |
| children    | Function         | Yes                         |            | Render function for each item (item, index, dataUid) => ReactNode |

## children Render Function Parameters

| Parameter | Type   | Description                       |
| --------- | ------ | --------------------------------- |
| item      | Object | Current data item                 |
| index     | Number | Current item index                |
| dataUid   | String | Unique identifier attribute value |

## Usage Scenarios

### 1. Fixed Height Mode

When all items have the same height, use fixed height mode:

```tsx
<AsyncVirtualScroll value={enabled} data={largeList} itemSize={60}>
  {(item) => <div>{item.text}</div>}
</AsyncVirtualScroll>
```

### 2. Dynamic Height Mode

When items have varying heights, use dynamic height mode:

```tsx
<AsyncVirtualScroll value={enabled} data={varyingHeightList} minItemSize={40}>
  {(item) => <div>{item.text}</div>}
</AsyncVirtualScroll>
```

### 3. Disable Virtual Scroll for Small Datasets

```tsx
<AsyncVirtualScroll data={list} ban={list.length < 100}>
  {(item) => <div>{item.text}</div>}
</AsyncVirtualScroll>
```

### 4. Custom Buffer

```tsx
<AsyncVirtualScroll data={list} buffer={[150, 300]}>
  {(item) => <div>{item.text}</div>}
</AsyncVirtualScroll>
```

## Notes

1. **The `value` prop is required (controlled mode)**
2. **Dynamic height mode requires `minItemSize` for initial height estimation**
3. **Performance Recommendations**
   - Prefer `itemSize` for fixed height
   - Set a reasonable `buffer` for better experience
   - Avoid complex calculations in `children`
4. **Data changes automatically trigger layout updates**

## Why Virtual Scroll?

Traditional rendering of large data lists causes:

- **High memory usage**: Thousands of DOM nodes
- **Low rendering performance**: Frequent browser layout and repaint
- **Interaction lag**: Obvious delays in scrolling and operations

**Asynchronous Virtual Scroll** addresses these issues by:

- 🚀 **On-demand rendering**: Only renders visible area
- ⏱ **Asynchronous calculation**: Uses IntersectionObserver to detect visibility
- 🔄 **Smart buffering**: Preloads buffer elements for smoother scrolling
- 📊 **Height caching**: Records rendered item heights to avoid recalculation

## License

MIT License