Reputation: 45
Currently trying to make modals in React and want to make a grid where "button 1" shows "modal 1" and "button 2" shows "modal 2" etc. At the moment when I press my button to show a modal it shows both modal 1 and modal 2. How do I set it up so button 1 only opens modal 1?
This is my App.js:
import React from 'react';
import './main.css';
import Modal from './components/Modal/modal';
class App extends React.Component {
state = {
show: false
};
showModal = x => {
this.setState({
show: !this.state.show
});
};
render() {
return (
<div>
<div className="button-container">
<button className="toggle-button" onClick={x => {
this.showModal(x);
}}>Show yourself Modal!</button>
</div>
<Modal onClose={this.showModal} show={this.state.show} title="Test modal 1" id="1">Lorem ipsum</Modal>
<Modal onClose={this.showModal} show={this.state.show} title="Test modal 2" id="2">I am a different modal</Modal>
</div>
);
}
}
export default App;
And this is my modal.js component:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import './modal.css';
export default class Modal extends Component {
onClose = x => {
this.props.onClose && this.props.onClose(x);
};
render() {
if(!this.props.show) {
return null;
}
return (
<div className="modal-wrapper">
<h2 className="modal-header">{this.props.title}</h2>
<div>{this.props.children}</div>
<div>
<button className="modal-close" onClick={this.onClose}></button>
</div>
</div>
)
}
}
Modal.propTypes = {
onClose: PropTypes.func.isRequired,
show: PropTypes.bool.isRequired
};
Upvotes: 1
Views: 898
Reputation: 96
If you require Button
for every Modal and control its behaviour with it then you can introduce a state to the modal component itself by doing something like this:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import './modal.css';
export default class Modal extends Component {
constructor(props) {
super(props);
this.state = {
showModal: false,
}
}
toggleShow = () => {
const { showModal } = this.state;
this.setState({showModal: !showModal})
};
render() {
const { showModal } = this.state;
return (
<div className="modal-wrapper">
{ showModal &&
<div>
<h2 className="modal-header">{this.props.title}</h2>
<div>{this.props.children}</div>
</div>
}
<div>
<button className="modal-close" onClick={() => this.toggleShow()}>{this.props.btnText}</button>
</div>
</div>
)
}
}
It can be build further to alter the default behaviour. This should clean your App.js
code.
Upvotes: 1
Reputation: 14385
The simplest way would be to add a second key to your state so that you have a way to manage showing both modals independently.
class App extends React.Component {
state = {
show1: false,
show2: false
};
Then make your change function to be a curried function that accepts a parameter to update the correct part of state. In order to use a variable to access an object key, we need to access it as an array like this:
showModal = (modal) => (e) => {
this.setState({
[modal]: !this.state[modal]
});
};
Then use it like this:
render() {
return (
<div>
<div className="button-container">
<button className="toggle-button" onClick={this.showModal('show1')}>Show yourself Modal 1!</button>
<button className="toggle-button" onClick={this.showModal('show2')}>Show yourself Modal 2!</button>
</div>
<Modal onClose={this.showModal('show1')} show={this.state.show1} title="Test modal 1" id="1">Lorem ipsum</Modal>
<Modal onClose={this.showModal('show2')} show={this.state.show2} title="Test modal 2" id="2">I am a different modal</Modal>
</div>
);
}
}
Upvotes: 2
Reputation: 20057
At the moment you have nothing in your state to tell which modal to show. You're using this.state.show
to control the visibility of both modals.
You could introduce a state property in your App
component which is used to choose which modal to show. For example, passing in a modalId
or similar to your click handler. (disclaimer: untested syntax, but the principal is right!)
So your state may look like this:
state = {
[
{
id: 1,
show: false
},
{
id: 2,
show: false
},
]
}
Then, in your click handler, you'd need to pass in the id of the modal to show / hide. You'd need to determine this from something in your UI.
showModal(id) => {
this.setState({
[id]: !this.state[id].show
})
}
Upvotes: 1