React Bootstrap Table имеет кнопку в каждой строке для создания модального окна, но одна кнопка будет вызывать модальное отображение несколько раз.

У меня React Bootstrap Table, на каждой странице таблицы 20 записей. В каждой строке я добавил кнопку, используя следующую строку

function attachFormatter(cell, row){
     return (
        <AttachmentManager />
     );
 }
 <TableHeaderColumn key={uuid.v4()}
                   dataField={column.dataField}
                   dataFormat={attachFormatter}
                   hidden={hide}>
                    {column.label}
</TableHeaderColumn>

Тогда у меня есть 20 кнопок на этой странице, и в каждой строке есть одна кнопка. Я намеревался открыть модальное окно, если нажму одну из кнопок. Но когда я нажимаю одну кнопку, openModal() запускается один раз, как и ожидалось, а функция render() моего AttachmentManager запускается 20 раз. Как это решить?

export default class AttachmentManager extends React.Component {
    constructor (props) {
        super(props);
        this.state = {showModal: false};
    }

    openModal() {
        alert('test');
    }

    render () {
        return (
      <button onClick={this.openModal.bind(this)} className="btn btn-default">Add Projects
        <AttachmentModal show={this.state.showModal}/>
      </button>
        );
    }
}

И следующее мое модальное

import React from 'react';
import SimpleModal from '../common/SimpleModal';
export default class AttachmentModal extends React.Component {

    constructor (props) {
        super(props);
    }

    render () {
        return (
            <SimpleModal showModal={this.props.show}
                       onToggleModal={this.props.onHide}
                       title={this.props.title}
                       onCancelClick={this.props.onHide}
                       onPrimaryButtonClick={this.props.onPrimaryButtonClick}
                       cancelText="Cancel"
                       primaryButtonText={this.props.primaryButtonText}
                       loading={this.props.loading}
                       backdrop='static'
                       bsStyle={this.props.bsStyle}>
                {this.props.children}
            </SimpleModal>
        );
    }
}

person Thomas    schedule 27.10.2017    source источник


Ответы (2)


Я также столкнулся с подобной проблемой и решил ее так.

В attachFormatter передайте значение row в качестве реквизита

function attachFormatter(cell, row){
     return (
        <AttachmentManager row={row} />
     );
 }
 <TableHeaderColumn key={uuid.v4()}
                   dataField={column.dataField}
                   dataFormat={attachFormatter}
                   hidden={hide}>
                    {column.label}
</TableHeaderColumn>

В AttachmentManager при нажатии кнопки устанавливается значение selectedRow и showModal. Вы можете использовать функцию isObjectEquivalent для сравнения свойств строки и значения selectedRow.

export default class AttachmentManager extends React.Component {
  constructor(props) {
   super(props);
   this.state = {
    showModal: false,
    selectedRow: null
   };
  }

  openModal() {
   this.setState((prevState, props) => {
    return {
     selectedRow: props.row,
     showModal: true
    }
   });
  }

  isObjectEquivalent(a, b) {
   // Create arrays of property names
   var aProps = Object.getOwnPropertyNames(a);
   var bProps = Object.getOwnPropertyNames(b);

   // If number of properties is different,
   // objects are not equivalent
   if (aProps.length != bProps.length) {
    return false;
   }

   for (var i = 0; i < aProps.length; i++) {
    var propName = aProps[i];

    // If values of same property are not equal,
    // objects are not equivalent
    if (a[propName] !== b[propName]) {
     return false;
    }
   }

   // If we made it this far, objects
   // are considered equivalent
   return true;
  }

  render() {
    return ( 
    <div>
        <button onClick = {this.openModal.bind(this)} className = "btn btn-default"> Add Projects </button> 
        {this.state.showModal && this.isObjectEquivalent(this.props.row, this.state.selectedRow) ? ( < AttachmentModal show = {this.state.showModal} />) : null} 
     </div>
      );
     }
    }

Надеюсь, это поможет вам.

person Syed    schedule 29.10.2017

Измените свой компонент на PureComponent.

export default class AttachmentManager extends React.PureComponent {
...
}

Добавьте ключ ко всем вашим кнопкам.

 <button key={uuid.v4()} onClick={this.openModal.bind(this)} className="btn btn-default">Add Projects
        <AttachmentModal show={this.state.showModal}/>
      </button>
person palsrealm    schedule 27.10.2017
comment
Все тот же. Когда я нажимаю одну кнопку, render() вызывается 20 раз. - person Thomas; 27.10.2017
comment
Можете ли вы добавить код для AttachmentModal к вашему вопросу? - person palsrealm; 27.10.2017
comment
См. отредактированный код. Несмотря на то, что я удалил строку <AttachmentModal show={this.state.showModal}/> в AttachmentManager, чтобы позволить рендерингу создавать только кнопку, рендеринг все равно выполняется несколько раз. - person Thomas; 27.10.2017
comment
Какой метод рендеринга выполняется 20 раз? AttachmentModal или SimpleModal? - person palsrealm; 28.10.2017
comment
метод рендеринга AttachmentManager - person Thomas; 28.10.2017