Реагировать на проблемы с производительностью виртуализированной многосеточной сети

#sql #reactjs #grid #react-virtualized

#sql #reactjs #сетка #react-виртуализированный

Вопрос:

Я пытаюсь создать хорошее представление результатов для просмотра результатов SQL-запроса. Эти результаты могут содержать тысячи результатов, поэтому был выбран React Virtualized, чтобы избежать отображения всех строк. Компонент MultiGrid был выбран таким образом, чтобы имена столбцов из запроса были привязаны к верхней части представления. Компонент выглядит следующим образом:

Многосеточный компонент

Многосеточная сеть имеет динамическую ширину с использованием средства измерения ячеек. Код сильно вдохновлен приведенным здесь примером. Моя проблема в том, что компонент отображается очень медленно, и в тех случаях, когда компонент был отображен, затем скрыт, а затем снова отображен, все приложение зависает на минуту или более. Очевидно, что отображается что-то, чего не должно быть, но я не уверен, в чем проблема. Я попытался очистить CellMeasurerCache, но это, похоже, не сработало. Код для многосеточной сети выглядит следующим образом:

 const useStyles = makeStyles((theme) => ({
  tableWrapper: {
    minHeight: 200,
    height: '100%',
    width: '100%',
    resize: 'vertical',
    overflowY: 'hidden',
    scrollbarWidth: 'none',
    paddingBottom: theme.spacing(2),
  },
  gridCell: {
    whiteSpace: 'nowrap',
    width: '100%',
    height: '100%',
    display: 'flex',
    flexDirection: 'column',
    paddingLeft: '1em',
    paddingRight: '1em',
    justifyContent: 'center',
  },
}));

export default function ResultTable() {
  const recordingContext = useContext(RecordingContext);

  const classes = useStyles();

  const result = recordingContext?.activeRecording?.queryOutput;

  if (!result || !result.results) {
    return (
      <Typography style={{ padding: '8px 16px' }} variant="subtitle1">
        No data to show
      </Typography>
    );
  }

  const { labels, types, values } = result.results;

  function formatDate(d: Date) {
    let month = `${d.getMonth()   1}`;
    let day = `${d.getDate()}`;
    const year = d.getFullYear();

    if (month.length < 2) month = `0${month}`;
    if (day.length < 2) day = `0${day}`;

    return [year, month, day].join('-');
  }

  function format(index: number, entry: unknown): string {
    let datatype = 0;
    if (types) {
      datatype = types[index];
    }
    if (datatype === 12) {
      if (typeof entry === 'number') {
        const date = new Date(Number(entry));
        return formatDate(date);
      }
      const date = new Date(String(entry));
      return formatDate(date);
    }
    return String(entry);
  }

  const STYLE: CSSProperties = {
    width: '100%',
    fontFamily: 'raleway',
    resize: 'none',
  };

  const cache = new CellMeasurerCache({
    defaultWidth: 100,
    fixedHeight: true,
  });

  type CellRendererType = {
    rowIndex: number;
    columnIndex: number;
    style: React.CSSProperties;
    parent: MeasuredCellParent;
  };

  function cellRenderer({
    rowIndex,
    parent,
    columnIndex,
    style,
  }: CellRendererType) {
    const content =
      rowIndex === 0
        ? labels[columnIndex]
        : format(columnIndex, values[rowIndex - 1][columnIndex]);
    return (
      <CellMeasurer
        cache={cache}
        parent={parent}
        key={`${columnIndex}-${rowIndex}`}
        columnIndex={columnIndex}
        rowIndex={rowIndex}
      >
        <div
          style={style}
          key={`${columnIndex}-${rowIndex}`}
          className={classes.gridCell}
        >
          {content}
        </div>
      </CellMeasurer>
    );
  }
  return (
    <div className={classes.tableWrapper}>
      <div
        style={{
          minHeight: 201,
          height: '100%',
          width: '100%',
          paddingBottom: 1,
        }}
      >
        <AutoSizer>
          {({ height, width }) => (
            <MultiGrid
              cellRenderer={cellRenderer}
              columnWidth={cache.columnWidth}
              columnCount={labels.length}
              height={height}
              deferredMeasurementCache={cache}
              rowHeight={48}
              rowCount={values.length   1}
              scrollToColumn={0}
              scrollToRow={0}
              fixedRowCount={1}
              width={width}
              style={STYLE}
              styleTopRightGrid={{
                fontWeight: 'bold',
                width: '100%',
                backgroundColor: '#404040',
                fontSize: 14,
              }}
              styleBottomRightGrid={{
                outline: 'none',
              }}
              overscanColumnCount={0}
              overscanRowCount={20}
            />
          )}
        </AutoSizer>
      </div>
    </div>
  );
}
  

Комментарии:

1. Я смог выяснить, что проблема связана с cellmeasurer, устранение этого привело к хорошей загрузке компонента. Это оставляет проблему сетки, не имеющей динамической ширины, так есть ли какой-либо способ исправить это?