最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React Virtualized - Nested WindowScrollerList - Stack Overflow

programmeradmin2浏览0评论

I'm trying to used react-virtualized to render a table with 1000+ rows of data. The rows are very heavy containing multiple plex React ponents. input, bobox, date selector and popup menus all in one single row. I need the entire window to scroll these rows.

I also need to group the rows and nest them into a show/hide style accordion ponent.

[+] Row Header 1
    row 1
    row 2
    ...
    row 1001
[+] Row Header 2
    row 1
    row 2
    ...
    row 1001

I'm unsure how to handle this use case or if React-Virtualized can handle this type of thing.

What I've tried:

Use WindowScroller/AutoSizer/List ponents in conjunction and place this group of react-virtualized ponents into each of the accordions. This works but does not solve my perf. issues because it's still too much for the browser to handle (first load is around 25 seconds and scrolling isn't usable)

Do I also need to use WindowScroller/AutoSizer/List ponents to handle the first level of Row Headers as well?

Any ideas or examples would be much appreciated.

I'm trying to used react-virtualized to render a table with 1000+ rows of data. The rows are very heavy containing multiple plex React ponents. input, bobox, date selector and popup menus all in one single row. I need the entire window to scroll these rows.

I also need to group the rows and nest them into a show/hide style accordion ponent.

[+] Row Header 1
    row 1
    row 2
    ...
    row 1001
[+] Row Header 2
    row 1
    row 2
    ...
    row 1001

I'm unsure how to handle this use case or if React-Virtualized can handle this type of thing.

What I've tried:

Use WindowScroller/AutoSizer/List ponents in conjunction and place this group of react-virtualized ponents into each of the accordions. This works but does not solve my perf. issues because it's still too much for the browser to handle (first load is around 25 seconds and scrolling isn't usable)

Do I also need to use WindowScroller/AutoSizer/List ponents to handle the first level of Row Headers as well?

Any ideas or examples would be much appreciated.

Share Improve this question asked Sep 13, 2018 at 4:11 jerpsu15jerpsu15 3411 gold badge4 silver badges5 bronze badges 3
  • On the same issue right now. Have you find a nice solution to share? Currently thinking about two possible options: 1) using virtualized Grids on each level (Grid for groups and a grid for subItems when the row is expanded) 2) use only one virtualized grid, prepare my data to tree-like structure and just change rowCount when expanding items – Mike Yermolayev Commented Nov 27, 2019 at 12:20
  • Do you need to display all of those ponents, or you only have a header that will later be expanded showing the plex ponent structure? – Ivan Satsiuk Commented Jan 14, 2021 at 18:20
  • I wrote a response to a similar question here. I hope this helps you. – yatsemirsky Commented Sep 24, 2023 at 8:16
Add a ment  | 

2 Answers 2

Reset to default 1

You can at least free up the UI thread for scrolling (of course an important UX principle) with web workers.

Here is a medium-length discussion article with an example, a quick implementation doc (and the great matching article), and my all-time favorite talk on the subject.

This defers the effort from the main "UI" thread, but you can also prevent this deferment in the first place if the effort can be memoized with the useMemo() hook.

The critical piece of react-virtualized is reputeRowHeights you can achieve the desired results with this.

import React, { useState, useRef, useEffect } from "react";
import {
  AutoSizer,
  Column,
  Table,
  defaultTableRowRenderer
} from "react-virtualized";

const Component = ({ list }) => {
  const [selectedIndex, setSelectedIndex] = useState(-1);
  const tableRef = useRef();

  const Details = ({ children, index }) => (
    <div style={{ cursor: "pointer" }} onClick={() => setSelectedIndex(index)}>
      {children}
    </div>
  );

  const _getDatum = index => list[index % list.length];
  const _getRowHeight = ({ index }) => (index === selectedIndex ? 96 : 48);
  const rowGetter = ({ index }) => _getDatum(index);
  const cellRenderer = ({ rowIndex }) => {
    if (rowIndex !== selectedIndex) {
      return <Details index={rowIndex}>+</Details>;
    } else {
      return <Details index={-1}>-</Details>;
    }
  };

  useEffect(
    () => {
      tableRef.current.reputeRowHeights();
    },
    [selectedIndex]
  );

  const rowRenderer = props => {
    const { index, style, className, key, rowData } = props;
    if (index === selectedIndex) {
      return (
        <div
          style={{ ...style, display: "flex", flexDirection: "column" }}
          className={className}
          key={key}
        >
          {defaultTableRowRenderer({
            ...props,
            style: { width: style.width, height: 48 }
          })}
          <div
            style={{
              marginRight: "auto",
              marginLeft: 80,
              height: 48,
              display: "flex",
              alignItems: "center"
            }}
          >
            {rowData.details}
          </div>
        </div>
      );
    }
    return defaultTableRowRenderer(props);
  };

  return (
    <div style={{ height: "90vh" }}>
      <AutoSizer>
        {({ width, height }) => (
          <Table
            ref="Table"
            headerHeight={56}
            height={height}
            overscanRowCount={10}
            rowHeight={_getRowHeight}
            rowGetter={rowGetter}
            rowCount={1000}
            width={width}
            ref={tableRef}
            rowRenderer={rowRenderer}
          >
            <Column
              label="Index"
              cellDataGetter={({ rowData }) => rowData.length}
              cellRenderer={cellRenderer}
              dataKey="index"
              disableSort
              width={60}
            />
            <Column dataKey="name" disableSort label="Full Name" width={120} />
          </Table>
        )}
      </AutoSizer>
    </div>
  );
};

export default Component;

Here is the codesandbox

发布评论

评论列表(0)

  1. 暂无评论