react-virtualized

repository·master·Indexed 12 days ago

https://github.com/bvaughn/react-virtualized

A collection of React components for efficiently rendering large, scrollable lists and complex tabular data through virtualization. Version 9.22.6 includes core components like List, Grid, Table, and Masonry, as well as High-Order Components such as AutoSizer for responsive dimensions, CellMeasurer for dynamic content sizing, and InfiniteLoader for lazy-loading datasets.

Tokens
32.4K
Snippets
86
Records
128
Agent score
97%

What's inside react-virtualized

  1. Overview of react-virtualized

    master
    react-virtualized provides React components for efficiently rendering large lists and tabular data. It is designed to handle high-performance scrolling and virtualization to maintain smooth UI interactions even with massive datasets.
  2. Explore react-virtualized components and HOCs

    master

    The react-virtualized library provides several core components and High-Order Components (HOCs) to handle large datasets efficiently.

    Core Components

    • Collection: A generic base for virtualized collections.
    • Grid: A two-dimensional virtualized grid.
    • List: A one-dimensional virtualized list.
    • Masonry: A masonry-style layout for items of varying sizes.
    • Table: A virtualized table, which includes support for Column and SortDirection components.

    High-Order Components (HOCs)

    • ArrowKeyStepper: Enables keyboard navigation.
    • AutoSizer: Automatically sizes the component to fit its parent container.
    • CellMeasurer: Measures the size of cells for dynamic content.
    • ColumnSizer: Manages column sizing in grids or tables.
    • InfiniteLoader: Handles loading data in chunks as the user scrolls.
    • MultiGrid: Manages multiple synchronized grids.
    • ScrollSync: Synchronizes scrolling between multiple components.
    • WindowScroller: Synchronizes scrolling with the browser window.
  3. How the Masonry component works

    master

    The Masonry component uses windowing to efficiently display dynamically-sized, user-positioned cells. It operates in two distinct phases:

    1. Measurement Phase: Uses estimated cell sizes from cellMeasurerCache to batch-measure items. It uses a naive layout algorithm to stack items until the viewport is filled. Measurements are permanently cached using a keyMapper to ensure performance. If actual sizes differ from estimates, a new measurement pass is triggered.
    2. Layout Phase: Uses an external cellPositioner function to determine the exact { left, top } coordinates for each cell. The Masonry component caches these returned positions for fast access.

    Key Constraints:

    • Vertical Windowing: It only supports vertical scrolling; horizontal scrolling is not supported.
    • Column Alignment: All items in a single column must have the same width and the same left position. Items cannot span multiple columns.
    • Synchronous Measurement: Cell measurements must be synchronous. Using the asynchronous measure parameter in CellMeasurer is not supported because it would cause frequent layout invalidation.
    • Animations: Supports simple animations (like sliding into place on initial reveal) but does not support complex animations like flying from one position to another during a resize.
  4. Implement the rowRenderer function

    master

    The rowRenderer is a required function responsible for rendering a single row. It is called for each row that needs to be rendered.

    Crucial Requirements:

    1. Apply style: You MUST pass the provided style object to the root element of your rendered row. This object contains the position, left, top, height, and width necessary for the List to position the row correctly.
    2. Provide key: You MUST pass the provided key to the root element for React's reconciliation.
    3. Avoid Vertical Overflow: It is highly recommended that rows use overflow-y: hidden to prevent individual items from intercepting scroll events, which can break the list's scrolling behavior.

    Arguments provided to rowRenderer:

    • index: The index of the row.
    • isScrolling: Boolean indicating if the list is currently being scrolled.
    • isVisible: Boolean indicating if the row is visible (not just overscanned).
    • key: A unique key for the row.
    • parent: A reference to the List instance.
    • style: The style object required for positioning.
    function rowRenderer({
      index, // Index of row
      isScrolling, // The List is currently being scrolled
      isVisible, // This row is visible within the List
      key, // Unique key within array of rendered rows
      parent, // Reference to the parent List (instance)
      style, // Style object to be applied to row (to position it);
    }) {
      const content = isScrolling ? '...' : <User user={list[index]} />;
    
      return (
        <div key={key} style={style}>
          {content}
        </div>
      );
    }
  5. Use AutoSizer to automatically adjust dimensions

    master

    The AutoSizer component is a high-order component that automatically calculates and provides the width and height of its parent container to a single child. This is useful for components like List that require explicit dimensions but need to fill available space dynamically.

    Usage Pattern

    AutoSizer uses a render prop pattern. You must provide a function as its children prop. This function receives an object containing the current height and width and should return a React element.

    Important: Flexbox Warning

    Avoid placing AutoSizer as a direct child of a flexbox container. Because flex containers allow children to grow and AutoSizer greedily expands to fill space, this can trigger an infinite resize loop. To prevent this, wrap AutoSizer in a standard block element (like a <div>) inside the flex container.

    <AutoSizer>
      {({ height, width }) => (
        <List
          height={height}
          width={width}
          // ... other props
        />
      )}
    </AutoSizer>
  6. Use InfiniteLoader for just-in-time data fetching

    master

    The InfiniteLoader component manages the fetching of data as a user scrolls through a list or grid. It is designed to work best with List and Table components, but can also be used with Grid. Note that it is not compatible with the Collection component.

    To use it, you must provide a child function that renders your virtualized component and connects it to the loader using the provided onRowsRendered and registerChild parameters.

    <InfiniteLoader
      isRowLoaded={isRowLoaded}
      loadMoreRows={loadMoreRows}
      rowCount={remoteRowCount}
    >
      {({ onRowsRendered, registerChild }) => (
        <List
          onRowsRendered={onRowsRendered}
          ref={registerChild}
          {...otherProps}
        />
      )}
    </InfiniteLoader>
  7. Use WindowScroller to sync List or Table with window scroll

    master

    The WindowScroller component enables a Table or List component to be scrolled based on the window's scroll positions. This is ideal for creating layouts like Facebook or Twitter news feeds where the list is part of the main page scroll rather than inside a fixed-height container.

    Limitations:

    • It does not currently work with horizontally-scrolling Grid components, as horizontal scrolls reset the internal scrollTop. Use it with Table or List only.
    import React from 'react';
    import { List, WindowScroller } from 'react-virtualized';
    import 'react-virtualized/styles.css';
    
    // Basic usage pattern
    <WindowScroller>
      {({ height, isScrolling, onChildScroll, scrollTop }) => (
        <List
          autoHeight
          height={height}
          isScrolling={isScrolling}
          onScroll={onChildScroll}
          scrollTop={scrollTop}
          {...otherProps}
        />
      )}
    </WindowScroller>
  8. Track loaded rows manually in InfiniteLoader

    master

    Because InfiniteLoader is not a stateful component, it does not track which rows have been requested. You must manage this state in your own component to prevent duplicate loading requests. A common pattern is to use a map to track the status (e.g., LOADING or LOADED) of each row index.

    _isRowLoaded ({ index }) {
      const { loadedRowsMap } = this.state
    
      // No entry in this map signifies that the row has never been loaded before
      // An entry (either LOADING or LOADED) can be treated as loaded as far as InfiniteLoader is concerned
      return !!loadedRowsMap[index]
    }
  9. How to trigger re-renders for shallowCompare changes

    master

    By default, all react-virtualized components use shallowCompare to avoid unnecessary re-renders. If your data changes (e.g., a list is re-sorted) but the props passed to the component remain the same (e.g., the array reference or length hasn't changed), the component may not update.

    Method 1: Pass-thru props

    Pass an additional property that changes when your data changes. shallowCompare will detect changes to any prop, even those not declared in propTypes.

    Example for a sorted list:

    <List {...listProps} sortBy={sortBy} />

    Method 2: Public methods

    You can force a re-render using specific component methods:

    • Grid and Collection: Use the standard React forceUpdate() method.
    • Table and List: Call forceUpdateGrid() to ensure the inner Grid is also updated.
    • MultiGrid: Call forceUpdateGrids() to ensure all inner Grids are updated.
  10. How AutoSizer works

    master

    The AutoSizer component decorates a React element and automatically manages width and height properties so that the decorated element fills the available space. This is useful for components like Grid, Table, and List that require explicit dimensions.

    Important Implementation Details:

    • It uses the javascript-detect-element-resize algorithm.
    • It performs direct DOM manipulation on its parent outside of React's VirtualDOM.
    • If the parent has position: static (the default), AutoSizer will change it to position: relative.
    • It injects a sibling div to measure size.
    <AutoSizer>
      {({ width, height }) => (
        <Component width={width} height={height} />
      )}
    </AutoSizer>
  11. How ScrollSync synchronizes scrolling between components

    master

    ScrollSync is a Higher Order Component (HOC) designed to synchronize the scroll position between two or more virtualized components (such as Grid or List).

    It works by providing a render function as its child. This function receives the current scroll state and an onScroll callback. To enable synchronization, you must pass the onScroll callback to at least one of the child components. When that component scrolls, the onScroll function updates the shared scroll offsets (scrollTop, scrollLeft, etc.), which are then passed down to the other components to keep them in sync.

    <ScrollSync>
      {({ onScroll, scrollTop, scrollLeft }) => (
        <>
          {/* Pass onScroll to one component to drive the sync */}
          <Grid onScroll={onScroll} scrollTop={scrollTop} scrollLeft={scrollLeft} {...otherProps} />
          
          {/* Pass the scroll offsets to the other component to keep it in sync */}
          <List scrollTop={scrollTop} scrollLeft={scrollLeft} {...otherProps} />
        </>
      )}
    </ScrollSync>