如何在React Virtualized行中呈现高度未知的多个表单模式

时间:2019-04-25 15:10:07

标签: react-virtualized react-jsonschema-forms

我目前正在从事一个项目,该项目中有一长页信息,出于分类目的,这些信息会分成多个部分。每个部分都有一个标头,用于说明该部分是什么,该部分的主体是通过react-jsonschema-form动态生成的。然后,用户可以填写或操纵每个部分以更改他们看到的数据,因此这些部分可以根据选择或保存的选项进行扩展或收缩(选中一个复选框,可能会出现另一个字段,要求您详细说明选择内容) 。因为有很多部分,我们认为最好对它们进行虚拟化,但是我们遇到了用适当的高度进行渲染和滚动的问题。

我们正在使用React 16.8.6,@ material-ui / core 3.9.2,react-jsonschema-form 1.4.0和react-virtualized 9.21.0。我设置了一个WindowScroller,并在其中放置了AutoSizer(以便在所有内部元素上提供响应宽度),然后使用一个List组件来呈现我的部分(格式为材料UI组件,并包含JsonSchema表单。

我能够生成这些节,但是它们最初的显示高度仅为71px,其中包括节头的高度和距主体的填充(但没有内容)。我已经设置了CellMeasurerCellMeasurerCache,所以我们将高度存储在所说的缓存中,但是它们始终显示为71px ...一旦节头在标题之后片刻就正确呈现,它们就不会重置出现。我决定在clearAll()的{​​{1}}属性中放置一个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(并且我认为这是确定当前位置及其下一步要呈现的内容),我想知道是否有一种方法可以简化此过程,也可以使其不频繁启动以将通话次数保持在最低水平。或者也许有一种方法可以虚拟化一个部分的内容,而不是整个行本身?只是想弄清楚是否有一种方法可以使用反应虚拟化来实现我的目标,或者我是否必须在这里“推出自己的解决方案”。谢谢!

0 个答案:

没有答案