How To Render Dialog Component In A Modal Using ReactJS
Renders a dialog component in a modal, controllable through events. To use the component, import ModalDialog
only once and then display it using ModalDialog.show()
, passing the JSX templates and data as parameters.
Define modalHandler
, a method that will handle showing the modal dialog, set state
to the default values initially and bind the close
and modalClick
methods to the component's context. Define close
and modalClick
to toggle the visibility of the modal dialog, based on state.closeOnClick
. Use the CustomEvent API to listen for modal
events, that can be dispatched from the static show()
method, handle listeners appropriately from componentDidMount
and componentWillUnmount
.
The show()
method accepts an argument, that should contain three parameters:
title
, a string for the dialog's titlecloseOnClick
, true if the modal should close on click or false if it should only close when clicking the X buttoncontent
, which is the JSX content to be rendered inside the dialog
Finally, in the render()
method, use a <div>
to wrap everything and render the modal dialog with the content passed to show()
.
App.css:
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
z-index: 9998;
display: flex;
justify-content: center;
align-items: center;
}
.dialog {
background-color: white;
border-radius: 5px;
overflow: hidden;
}
.dialog-title {
box-sizing: border-box;
width: 100%;
height: 48px;
padding: 0 16px;
border-bottom: 0.5px solid #c3c3c3;
display: flex;
justify-content: space-between;
align-items: center;
}
.dialog-close {
font-size: 32px;
color: #c3c3c3;
cursor: pointer;
transform: rotate(45deg);
user-select: none;
}
.dialog-close:hover {
color: red;
}
.dialog-content {
min-width: 300px;
}
App.js:
class ModalDialog extends React.Component {
constructor() {
super();
this.modalHandler = (e) => {
this.setState({
data: e.detail.data,
visible: true
});
};
this.state = {
data: {
title: '',
closeOnClick: false,
content: ''
},
visible: false
};
this.close = this.close.bind(this);
this.modalClick = this.modalClick.bind(this);
}
render() {
return !this.state.visible ? null : <div className="modal" onClick={this.modalClick}>
<div className="dialog">
<div className="dialog-title">{ this.state.data.title }<span className="dialog-close" onClick={this.close}>+</span></div>
<div className="dialog-content">
{
this.state.data.content
}
</div>
</div>
</div>
}
componentDidMount() {
document.addEventListener('modal', this.modalHandler);
}
componentWillUnmount() {
document.removeEventListener('modal', this.modalHandler);
}
close() {
this.setState({
visible: false,
data: {
title: '',
closeOnClick: false,
content: ''
}
});
}
static show(data) {
document.dispatchEvent(new CustomEvent('modal', {
detail: {
data
}
}));
}
modalClick() {
if (this.state.data.closeOnClick) this.close();
}
}
// add to render function
<ModalDialog />
// every time you wanna call the dialog
// content is a jsx element
ModalDialog.show({
title: 'Hello, world!',
closeOnClick: true,
content: <img src="https://images.app.goo.gl/8XvE3zkUXNNAqmmu8"/>
});
Note:
This component includes a lot of CSS, which might conflict with other CSS in your project. It is recommended for the modal to be a direct child of the body tag.
A more up-to-date method with lower compatibility is to use Portals in React 16+.
Happy Coding!