I am trying to render multiple react-bootsrap modals with map but I am unable to do so. With my current code clicking the 'View Details' button is activating all the modals at the same time instead of opening the relevant modal. Here's a snippet from my code related to the modal:
render() {
const { accounts } = this.props;
const displayAccounts = Object.keys(accounts).filter(key => {
return accounts[key].info.type === 'student'
}).map(key => {
return (
<tr key={key}>
<th>{accounts[key].info.name}</th>
<td>{accounts[key].info.email}</td>
<td><Button bsStyle='danger' onClick={() => this.props.removeAccount(key)}>Remove Account</Button></td>
<td>
<ButtonToolbar>
<Button id={key} bsStyle="primary" onClick={this.showModal}>View Details</Button>
<Modal
id={key}
show={this.state.show}
onHide={this.hideModal}
>
<Modal.Header closeButton>
<Modal.Title>Student Details</Modal.Title>
</Modal.Header>
<Modal.Body>
<Table responsive striped hover>
<thead>
<tr>
<th>Title</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<th>Name</th>
<td>{accounts[key].userDetails.name}</td>
</tr>
<tr>
<th>Education</th>
<td>{accounts[key].userDetails.education}</td>
</tr>
<tr>
<th>GPA</th>
<td>{accounts[key].userDetails.gpa}</td>
</tr>
<tr>
<th>Skills</th>
<td>{accounts[key].userDetails.skills}</td>
</tr>
<tr>
<th>Overview</th>
<td>{accounts[key].userDetails.skills}</td>
</tr>
</tbody>
</Table>
</Modal.Body>
<Modal.Footer>
<Button onClick={this.hideModal}>Close</Button>
</Modal.Footer>
</Modal>
</ButtonToolbar>
</td>
</tr>
)
})
I am trying to render multiple react-bootsrap modals with map but I am unable to do so. With my current code clicking the 'View Details' button is activating all the modals at the same time instead of opening the relevant modal. Here's a snippet from my code related to the modal:
render() {
const { accounts } = this.props;
const displayAccounts = Object.keys(accounts).filter(key => {
return accounts[key].info.type === 'student'
}).map(key => {
return (
<tr key={key}>
<th>{accounts[key].info.name}</th>
<td>{accounts[key].info.email}</td>
<td><Button bsStyle='danger' onClick={() => this.props.removeAccount(key)}>Remove Account</Button></td>
<td>
<ButtonToolbar>
<Button id={key} bsStyle="primary" onClick={this.showModal}>View Details</Button>
<Modal
id={key}
show={this.state.show}
onHide={this.hideModal}
>
<Modal.Header closeButton>
<Modal.Title>Student Details</Modal.Title>
</Modal.Header>
<Modal.Body>
<Table responsive striped hover>
<thead>
<tr>
<th>Title</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<th>Name</th>
<td>{accounts[key].userDetails.name}</td>
</tr>
<tr>
<th>Education</th>
<td>{accounts[key].userDetails.education}</td>
</tr>
<tr>
<th>GPA</th>
<td>{accounts[key].userDetails.gpa}</td>
</tr>
<tr>
<th>Skills</th>
<td>{accounts[key].userDetails.skills}</td>
</tr>
<tr>
<th>Overview</th>
<td>{accounts[key].userDetails.skills}</td>
</tr>
</tbody>
</Table>
</Modal.Body>
<Modal.Footer>
<Button onClick={this.hideModal}>Close</Button>
</Modal.Footer>
</Modal>
</ButtonToolbar>
</td>
</tr>
)
})
Share
Improve this question
edited Aug 6, 2017 at 21:40
Ghulam Ahmed
asked Aug 6, 2017 at 21:35
Ghulam AhmedGhulam Ahmed
1291 silver badge7 bronze badges
1 Answer
Reset to default 8Try making the following modifications...
Add the following change to this.state
in your constructor
to cache the active Modal index to be assigned later.
this.state = {
...,
activeModal: null,
...,
}
this.clickHandler = this.clickHandler.bind(this);
this.hideModal = this.hideModal.bind(this);
Add/Change the following Event Handlers. The clickHandler
accepts the click event as well as an index that will be used to set the aforementioned activeModal
piece of state. When react sees that the state changed it will call the render
method with the new state. This is the Reactive nature of React.
clickHandler(e, index) {
this.setState({ activeModal: index })
}
hideModal() {
this.setState({ activeModal: null })
}
Do something like this in your map
function. Notice the onClick
handler. Use an arrow function to catch the click event and call your clickHandler
, this is so you can also pass additional arguments (this index
in this case). Once the activeModal
piece of state is called the ponent will be rerendered, upon doing to the show
prop will evaluate to true for the appropriate clicked
ponent.
buttonArray.map((button, index) => {
<Button id={key} bsStyle="primary" onClick={e => this.clickHandler(e, index)}>View Details</Button>
<Modal
id={key}
show={this.state.activeModal === index}
onHide={this.hideModal}
/>
} )