Как отобразить несколько схем форм неизвестной высоты в строках React Virtualized - PullRequest
0 голосов
/ 25 апреля 2019

В настоящее время я работаю над проектом, в котором у нас есть длинная страница информации, которая разбита на разделы для целей категоризации.У каждого раздела есть заголовок, в котором указано, что это за раздел, а тело этого раздела генерируется с помощью response-jsonschema-form на лету.Затем каждый раздел может быть заполнен или изменен пользователем для изменения данных, которые он видит, так что разделы могут расширяться или сжиматься в зависимости от выбранных или сохраненных параметров (установите флажок, может появиться другое поле с просьбой уточнить ваш выбор),Поскольку разделов так много, мы подумали, что было бы хорошо их виртуализировать, но у нас возникают проблемы с рендерингом с правильной высотой и прокруткой.

Мы используем React 16.8.6, @ material-ui /ядро 3.9.2, реактивная-jsonschema-форма 1.4.0 и реактивная виртуализация 9.21.0У меня настроен WindowScroller с AutoSizer внутри (чтобы дать мне отзывчивую ширину для всех внутренних элементов), а затем я использую компонент List для рендеринга своих секций (отформатированных с помощью компонентов UI материала и содержащихJsonSchema Forms).

Я могу создать разделы, но каждый из них изначально имеет высоту всего 71 пиксель, что включает в себя высоту заголовка раздела и отступ от тела (но без содержимого).Я настроил CellMeasurer и CellMeasurerCache, поэтому у нас есть высота, сохраненная в указанном кэше, но они всегда отображаются как 71px ... они не сбрасываются после того, как тела секций должным образом отображаются через несколько секунд после появления заголовков.Я решил поместить clearAll() функцию в onRowsRendered свойство List, и это, кажется, сработало изначально, но как только я начинаю прокручивать, вещи начинают действовать все более и более дрянно, и затем все в конечном итоге падает сследующая ошибка:

Uncaught Invariant Violation: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

Журналы консоли показывают мне, что CellMeasurer постоянно срабатывает во время прокрутки, и я волновался, что это как-то стало причиной сбоя.Первоначально в моей консоли было второе сообщение об ошибке и трассировка стека, что привело меня к свойству withWidth компонента Hidden, который мы использовали для изменения размера области содержимого внутри наших разделов на разной ширине экрана, поэтому я подумал, что как-то константазапуск CellMeasurer заставлял компонент Hidden постоянно измерять его ширину, но я удалил этот компонент, и я все еще получил Invariant Violation сверху.Все, что было сделано, - это удаление второго сообщения об ошибке, и теперь я получаю бесконечную кучу сообщений журнала консоли, показывающих, что CellMeasurer постоянно срабатывает, даже после того, как я прекратил прокрутку, смешанную с периодическим сообщением об ошибке сверху.

Вот базовая схема моего кода:

import ResponsiveJsonForm from '../components/ResponsiveJsonForm'

class AssessmentForm extends React.Component {
  cache = new CellMeasurerCache({
    defaultHeight: 400,
    fixedWidth: true,
  })

  addFormRef = section => form => {
    if (form) {
      this.forms[section] = form
    }
  }

  attemptSubmit = section => success => {
    this.submissions[section] = success
    const successes = Object.values(this.submissions)

    if (successes.length === this.props.sections.length) {
      if (successes.every(Boolean)) {
        this.openSignDialog()
      }

      this.submissions = {}
    }
  }

  rowRenderer = ({ key, index, parent, isScrolling, isVisible, style }) => {
    const section = this.props.sections[index]
    return (
        <CellMeasurer
          cache={this.cache}
          columnIndex={0}
          key={key}
          parent={parent}
          rowIndex={index}
        >
          <div style={style}>
            <SectionForm
              key={section}
              assessmentId={this.props.assessmentId}
              section={section}
              FormComponent={ResponsiveJsonForm}
              formRef={this.addFormRef(section)}
              onSubmitAttempted={this.attemptSubmit(section)}
            />
          </div>
        </CellMeasurer>
      )
    )
  }

  render() {
    const {
      classes,
      sections,
    } = this.props

    return sections.length > 0 && (
      <div className={classes.root}>
        <WindowScroller>
          {({ height, isScrolling, onChildScroll, scrollTop }) => (
            <AutoSizer disableHeight>
              {({ width }) => (
                  <List
                    autoHeight
                    width={width}
                    deferredMeasurementCache={this.cache}
                    isScrolling={isScrolling}
                    onScroll={onChildScroll}
                    scrollTop={scrollTop}
                    ref={list => (this.list = list)}
                    height={height}
                    overscanRowCount={2}
                    onRowsRendered={() => {
                      this.cache.clearAll()
                    }}
                    rowCount={sections.length}
                    rowHeight={this.cache.rowHeight}
                    rowRenderer={this.rowRenderer}
                  />
                )
              }
            </AutoSizer>
          )}
        </WindowScroller>
    )
}

Мне интересно, прежде всего, правильно ли все это настроить ... и перечислить правильный компонент для использованиядля многих строк одной ячейки, карточки с заголовком и телом, которое содержит информацию о форме?Кроме того, поскольку при каждом движении прокрутки функция onRowRenderer, по-видимому, вызывается для запуска CellMeasurer (и я предполагаю, что она должна определять текущее позиционирование и то, что должно отображаться далее), мне было интересно, есть ли способчтобы упростить этот процесс или чтобы он не срабатывал так часто, чтобы звонки были минимальными.Или, может быть, существует способ виртуализации только содержимого раздела, а не всей строки?Просто пытаюсь выяснить, есть ли способ использовать реагирующую виртуализацию для достижения моих целей, или мне нужно «раскрутить свое» решение здесь.Спасибо!

...