CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-rc-virtual-list

React Virtual List Component which worked with animation

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

render-system.mddocs/

Render System

The render system provides the type interfaces and patterns for rendering list items with proper positioning and styling support.

Capabilities

Render Function Type

The core render function interface that defines how individual list items are rendered.

/**
 * Function type for rendering individual list items (available through ListProps.children)
 * @param item - The data item to render
 * @param index - Position of the item in the data array
 * @param props - Additional rendering properties
 * @returns React node representing the rendered item
 */
type RenderFunc<T> = (
  item: T,
  index: number,
  props: { 
    style: React.CSSProperties; 
    offsetX: number;
  }
) => React.ReactNode;

The render function is called for each visible item and receives:

  • item: The actual data from the data array
  • index: The item's position in the original data array
  • props.style: CSS styles for positioning (crucial for virtualization)
  • props.offsetX: Horizontal offset for horizontal scrolling

Usage Examples:

import List from "rc-virtual-list";

// Basic render function
<List data={items} height={300} itemHeight={50} itemKey="id">
  {(item, index) => (
    <div>{item.name}</div>
  )}
</List>

// Using all render parameters
<List data={items} height={300} itemHeight={50} itemKey="id">
  {(item, index, { style, offsetX }) => (
    <div 
      style={style} // Important: Apply the provided style
      className={index % 2 === 0 ? 'even' : 'odd'}
    >
      <span>#{index}: {item.name}</span>
      {offsetX > 0 && <span>Offset: {offsetX}px</span>}
    </div>
  )}
</List>

// Complex item rendering
<List data={products} height={400} itemHeight={80} itemKey="id">
  {(product, index, { style }) => (
    <div style={style} className="product-item">
      <img src={product.image} alt={product.name} />
      <div className="product-details">
        <h3>{product.name}</h3>
        <p>{product.description}</p>
        <span className="price">${product.price}</span>
      </div>
    </div>
  )}
</List>

Extra Render Information

Information provided to the extraRender function for advanced rendering scenarios.

/**
 * Information provided to extraRender function
 */
interface ExtraRenderInfo {
  /** First visible item index */
  start: number;
  /** Last visible item index */
  end: number;
  /** Whether virtualization is currently active */
  virtual: boolean;
  /** Current horizontal offset for horizontal scrolling */
  offsetX: number;
  /** Current vertical offset */
  offsetY: number;
  /** Whether the list is in RTL mode */
  rtl: boolean;
  /** Function to get size information for items */
  getSize: GetSize;
}

Usage Example:

import List from "rc-virtual-list";

const ListWithExtra = () => {
  const extraRender = (info: ExtraRenderInfo) => {
    return (
      <div style={{ 
        position: 'absolute', 
        top: 0, 
        right: 0, 
        padding: '8px',
        background: 'rgba(0,0,0,0.5)',
        color: 'white'
      }}>
        Showing items {info.start}-{info.end}
        {info.virtual && ' (virtualized)'}
      </div>
    );
  };

  return (
    <List
      data={data}
      height={300}
      itemHeight={50}
      itemKey="id"
      extraRender={extraRender}
    >
      {(item) => <div>{item.name}</div>}
    </List>
  );
};

Get Size Function Type

/**
 * Function to get size information for item ranges
 * @param startKey - Starting item key
 * @param endKey - Ending item key (optional)
 * @returns Size bounds information
 */
type GetSize = (
  startKey: React.Key, 
  endKey?: React.Key
) => { 
  top: number; 
  bottom: number; 
};

Shared Configuration

/**
 * Shared configuration object passed through the rendering system
 */
interface SharedConfig<T> {
  /** Function to extract keys from data items */
  getKey: (item: T) => React.Key;
}

Key Extraction Type

/**
 * Function type for extracting unique keys from data items
 */
type GetKey<T> = (item: T) => React.Key;

Best Practices

Style Application

Always apply the provided style prop to maintain proper virtualization:

// ✅ Correct - applies positioning styles
{(item, index, { style }) => (
  <div style={style}>
    {item.content}
  </div>
)}

// ❌ Incorrect - virtualization will break
{(item, index, { style }) => (
  <div>
    {item.content}
  </div>
)}

Key Stability

Use stable, unique keys for optimal performance:

// ✅ Good - stable unique key
itemKey="id"

// ✅ Good - function returning stable key
itemKey={(item) => item.uniqueId}

// ❌ Poor - unstable key
itemKey={(item) => Math.random()}

Performance Optimization

  • Keep render functions simple and avoid heavy computations
  • Use React.memo for complex item components
  • Avoid creating new objects/functions inside render functions
  • Cache expensive calculations outside the render function
// ✅ Optimized render function
const ItemComponent = React.memo(({ item, style }) => (
  <div style={style}>
    <h3>{item.title}</h3>
    <p>{item.description}</p>
  </div>
));

<List data={data} height={300} itemHeight={80} itemKey="id">
  {(item, index, { style }) => (
    <ItemComponent item={item} style={style} />
  )}
</List>

Install with Tessl CLI

npx tessl i tessl/npm-rc-virtual-list

docs

index.md

list-component.md

list-reference.md

render-system.md

scrolling.md

tile.json