0

I have a React Bootstrap Table, each page of the table has 20 records. In each row, I added a button using following line

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

Then I have 20 buttons in this page and each row has one button. I intended to open a modal if click one of the button. But when I click one button, the openModal() runs one time as expected, but the render() function of my AttachmentManager will run 20 times. How to solve this?

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>
        );
    }
}

And following is my modal

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>
        );
    }
}
Thomas
  • 1,805
  • 1
  • 15
  • 31

2 Answers2

1

I was also facing the similar problem and solved it like this.

In attachFormatter, pass the row value as props

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

In AttachmentManager, On click of button the set selectedRow and showModal value. You can use isObjectEquivalent function to compare the row props and selectedRow value.

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>
      );
     }
    }

Hope this help you.

Syed
  • 269
  • 2
  • 8
0

Change your component to a PureComponent.

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

Add a key to all your buttons.

 <button key={uuid.v4()} onClick={this.openModal.bind(this)} className="btn btn-default">Add Projects
        <AttachmentModal show={this.state.showModal}/>
      </button>
palsrealm
  • 5,083
  • 1
  • 20
  • 25