【问题标题】:All TableRows are rerendered each time a row is selected with React and material-ui每次使用 React 和 material-ui 选择一行时,都会重新渲染所有 TableRows
【发布时间】:2016-05-04 06:53:32
【问题描述】:

我有一个这样的代码 sn-p

<Table selectable onRowSelection={this.onRecordSelected} bodyStyle={tableBodyStyle}>
        <TableBody deselectOnClickaway={false} showRowHover displayRowCheckbox={false}>
          {this.props.taskRecords.map((row, index) => (
            <TableRow key={row.get('id')} selected={this.state.selectedRecordRowId === index}>
              <TableRowColumn>{row.getIn(['task', 'name'])}</TableRowColumn>
              <TableRowColumn>{row.getIn(['task', 'description'])}</TableRowColumn>
              <TableRowColumn>{row.get('status')}</TableRowColumn>
              <TableRowColumn>{row.get('log')}</TableRowColumn>
            </TableRow>
          ))}
        </TableBody>
</Table>

我查看了TableRowTableRowColumn的源代码,发现它们没有实现shouldComponentUpdate方法。我知道当任何状态发生变化时它们会被重新渲染。

我尝试使用recompose 库中的pure 函数将这些净化为组件。

const TableRow = pure(require('material-ui/lib/table/table-row'));
const TableRowColumn = pure(require('material-ui/lib/table/table-row-column'));

它们仍然被重新渲染

据我了解,如果props 不改变,纯化后的组件将不再重新渲染。在这种情况下,所有的 props 要么是来自 Immutable.js 的不可变对象,要么是函数。

当我选择任何行时,有什么方法可以防止它重新呈现?

提前谢谢你。

【问题讨论】:

    标签: javascript reactjs material-ui


    【解决方案1】:

    终于找到了解决办法。

    <Table selectable onRowSelection={this.onRecordSelected} bodyStyle={tableBodyStyle}>
            <TableBody deselectOnClickaway={false} showRowHover displayRowCheckbox={false}>
              {this.props.taskRecords.map((row, index) => (
                <PureRecordRow key={row.get('id')} selected={this.state.selectedRecordRowId === index}>
                  <TableRowColumn>{row.getIn(['task', 'name'])}</TableRowColumn>
                  <TableRowColumn>{row.getIn(['task', 'description'])}</TableRowColumn>
                  <TableRowColumn>{row.get('status')}</TableRowColumn>
                  <TableRowColumn>{row.get('log')}</TableRowColumn>
                </PureRecordRow>
              ))}
            </TableBody>
     </Table>
    

    我创建了一个新组件 PureRecordRow,它使用自定义 shouldComponentUpdate 方法扩展了 TableRow

    class PureRecordRow extends TableRow{
      constructor(props, context){
        super(props, context)
      }
      shouldComponentUpdate(nextProps, nextState) {
        return this.state.hovered !== nextState.hovered || this.props.selected !== nextProps.selected;
      }
    }
    

    【讨论】:

    • 无法扩展 TableRow
    【解决方案2】:

    一般来说,是的 - TableRowTableRowColumn 如果它们的父组件将被重新渲染,则每次都会调用 render 函数,但这还不错,因为 render 函数不会改变你的 RealDOM每次,所以它对您的应用程序性能并没有那么糟糕。 但是,如果您真的想阻止这种情况,例如,您可以创建新组件 MyRow 并渲染它而不是 TableRow + TableRowColumn

    所以,你的代码会是这样的:

    <Table selectable onRowSelection={this.onRecordSelected} bodyStyle={tableBodyStyle}>
        <TableBody deselectOnClickaway={false} showRowHover displayRowCheckbox={false}>
          {this.props.taskRecords.map((row, index) => (
            <MyRow key={index} row={row} isSelected={this.state.selectedRecordRowId === index} />
          ))}
        </TableBody>
    </Table>
    

    而在MyRow 组件中,您可以实现shouldComponentUpdate(或PureRenderMixin)并渲染真实的material-ui 组件:

    render() {
        var isSelected = this.props.isSelected;
        var row = this.props.row;
        return <TableRow key={row.get('id')} selected={isSelected}>
              <TableRowColumn>{row.getIn(['task', 'name'])}</TableRowColumn>
              <TableRowColumn>{row.getIn(['task', 'description'])}</TableRowColumn>
              <TableRowColumn>{row.get('status')}</TableRowColumn>
              <TableRowColumn>{row.get('log')}</TableRowColumn>
        </TableRow>
    }
    

    【讨论】:

    • 感谢您的解决方案!这种方法的问题是在将TableRow 包裹在MyRow 中之后,TableRow 的onSelect 处理程序无法正常工作。
    • 抱歉,我在TableRow 组件中没有看到任何onSelect 处理程序=/ 我已经检查了官方文档和github.com/callemall/material-ui/blob/master/src/Table/… 源文件
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-17
    • 1970-01-01
    • 2021-06-23
    • 2021-01-03
    • 1970-01-01
    • 2021-12-14
    相关资源
    最近更新 更多