What’s in this post?
In this article, I’ll guide you on how to build a dynamic Modal component from scratch which can be a general component in your project and receive a different body every single time you use it.

Prerequisites:
- Basic JavaScript knowledge.
- Basic ReactJS knowledge.
- Basic CSS knowledge.
Create a project
Alright, so first of all, we will need a project so we can implement our new Modal component, if you already have one then feel free to pass this step and continue to the next one.
In case you don’t have a project ready for that, let's create a new project using the following command:
npx create-react-app modal_tutorial
This command will generate a new ReactJS application named modal_tutorial.
Creating the Modal component
Next, organize your newly created React application and add a new folder under the src directory called components, and inside of it create another project and name it Modal with 2 files into it: index.js & index.css.
Past the following code in your index.js file:
import React, {useEffect, useRef} from 'react';import './index.css';const Modal = ({isOpen, toggleModal, closeOnOutsideClick, children}) => {
const modalRef = useRef(null);
useEffect(() => {
const handleClickOutside = (event) => {
if (closeOnOutsideClick && modalRef.current && !modalRef.current.contains(event.target)) {
toggleModal();
}
} // Bind the event listener
document.addEventListener('mousedown', handleClickOutside);
return() => {
// Unbind the event listener
document.removeEventListener('mousedown', handleClickOutside);
};}, [modalRef, closeOnOutsideClick, toggleModal];return (
<div className="modal" style={isOpen ? {display: 'none'} : null}>
<div className="modal__wrapper" ref={modalRef}>
{children}
</div>
</div>
)
}export default Modal;
Let me explain to you what you just copied:
- First, we’re going to request the parent component to provide us 4 different props:
- isOpen — Boolean, and should describe if the modal should be open right now or not.
- toggleModal — Function, which should change the value of isOpen.
- closeOnOutsideClick — Boolean, and should describe if we want to close the modal when we click outside of it or not.
- children — HTML element (such as div) which will be the body of our modal.
2. Defined a reference that will be used on the modal’s wrapper and will know its current state.
3. useEffect function, which will handle closing the modal in case we passed the closeOnOutsideClick as a truthy param.
4. The return HTML elements, that will be the wrapper of the modal and based on isOpen prop, we toggle the display of modal__wrapper div from none to flex (flex is in the CSS section below).
5. Exported the component so we can import it from other files in our project.
Add some style:
Let’s start by copying the following code to your index.css file:
.modal {
position: fixed;
display: flex;
justify-content: center;
align-items: center; z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
}.modal__wrapper {
position: absolute;
top: 50%;
width: 30%;
background: #fff;
text-align: center;
transform: translateY(-50%);
padding: 2rem;
border-radius: 18px;
box-shadow: 0 0 1rem 0 #ccc;
min-height: 200px;
display: flex;
justify-content: center;
align-items: center;
}
Let me explain to you what you just copied:
- We’ve styled the modal main div detecting it by its class name .modal, and we gave it a position fixed property together with height and width of 100%, and top and left properties at 0, so it will always fit the whole screen, next we gave it a background-color so the user will see the difference between the original screen and the opened modal.
We’ve also set the entire div displayed as flex and centered the whole modal so it will be displayed in the center of the screen. - Next, we’ve styled the modal’s wrapper div using its class name .modal__wrapper and we chose a position absolute and used the top property set to 50%, and transform: translateY(-50%) so it will center the modal’s wrapper to the middle of the screen even in cases that there’s a scrollbar needed.
After that, we gave it 30% width of the screen, aligned the text to the center of the div, and gave it some more properties of styling like padding, and box-shadow, and displayed the content of the wrapper in the center using display flex property.
Use the Modal component
Get into your src/App.js file and inside of it, import our newly created component using the following line on the top of the file:
import Modal from './components/Modal';
To use the Modal, you’ll have to define a few things:
- Define a new state using the useState hook which will be used to toggle the modal and describe its open status, and create a new function called toggleModal which will handle the change of the state:
import React, {useState} from 'react';
import Modal from './components/Modal';import './App.css';const App = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
const toggleModal = () => {
setIsModalOpen(!isModalOpen);
}return (
<div className="App">
<Modal isOpen={isModalOpen} toggleModal={toggleModal} closeOnOutsideClick={true}>
<div className="content">
Your content here...
</div>
</Modal>
<button onClick={toggleModal}>Open Modal</button>
</div>
);
}export default App;
Explanation:
- First, we’ve imported React and the useState hook so we can create a state using this hook, and we created the isModalOpen state, and initialized it to false, so the modal won’t be opened by default.
- Second, we defined a new method called toggleModal which is changing the isModalOpen state to the opposite of the current state, by this way, we’ll be able to toggle it from false to true and true to false.
- Next, we returned a modal with all the properties we defined in the modal component and passed isModalOpen to isOpen prop, toggleModal to the toggleModal prop, and true to closeOnOutsideClick so clicking outside of the modal will close it.
- We’ve added a button to the page which will handle the modal toggle so we will be able to toggle it and we passed toggleModal to the onClick prop of it.
The Result
Congratulations! You’ve made a dynamic modal component!
The modal should look something like that:
GitHub repository: https://github.com/RLeDEV/dynamic_modal
If you want to learn more, lookup for my previous articles: