Reusable Custom Modal With React Js

Infinitypaul
5 min readApr 13, 2019

--

The idea behind this tutorial is to the have a wrapping element which provides the styling that wraps itself around any content we want to show. i use this alot in most of my react project. here is a pictorial example of what am talking about (just like a bootstrap modal)

Modal

the above is a picture from one of my open source project built with react(available on github)

First and foremost let's install React with npm init react-app my-app

i won’t go into too much details about creating a react app in this tutorial, as i expect you to have the knowledge.

first and foremost i will create Modal.js in a UI folder (the structure of your folder is dependent on you), we will also need a Backdrop.js in the UI folder too and that can be reusable in other things you want to do

Here is the Modal.js code. it is going to be a functional component without any state attached to it. it just receives some props and return some JSX with a div wrapped around props.children so as to be able to receive any content, component, some text that is totally up to us, we can pass anything in there

import React from 'react';

const modal = props => {
return (
<div>
{props.children}
</div>
);
};


export default modal;

and of course the wrapping div should receive some styling to have a modal feeling, so am go create a new modal.module.css file, you can find the css code i used in creating the modal below

with that done, you can import the class from the modal.module.css to the modal.js,

import React from 'react';
import classes from 'Modal.module.css';

const modal = props => {
return (
<div className={classes.Modal}>
{props.children}
</div>
);
};


export default modal;

so you can add the modal.js wherever you want to display it. i will be importing mine to the App.js file

import Modal from '../src/UI/Modal/Modal'

and

         <Modal>
<div
style={{color:'black'}}
>
The Best Has Happened To ME
</div>
</Modal>

so i have something that looks like this

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Modal from '../src/UI/Modal/Modal'

class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
<Modal>
<div
style={{color:'black'}}
>
The Best Has Happened To ME
</div>
</Modal>
</header>
</div>
);
}
}

export default App;

reloading the page, we will have the Modal loaded on page load

Modal

The next step is to make sure we don’t always show the modal, but we can show the modal once we click Learn React

we need to add a state to determine if the Learn React Link was clicked

state={
modalToggle: false
}

i will add a new method called modalHandler, which should be triggered when we click on the Learn React

modalHandler = (e) => {
e.preventDefault(); //i added this to prevent the default behavior
this.setState({
modalToggle: true
})
}

Now i can conditionally render the Modal and since we added

transition: all 0.3s ease-out;

to the modal.module.css, it add a bit of animation when the Modal is shown , so let’s take advantage of it

So lets pass a Show property to the Modal we imported in the App.js file and bind it to the modalToggle state. only if the modalToggle is true the Modal should be visible

<Modal show={this.state.modalToggle}>
<div
style={{color:'black'}}
>
The Best Has Happened To ME
</div>
</Modal>

Let’s head over to the modal.js and adjust the code, so the Modal can react to the changes on the show property

i added a new inline style to control the opacity and the transform property

<div
className={classes.Modal}
style={{
transform:props.show ? 'translateY(0)' : 'translateY(-100vh)',
opacity : props.show ? 1 : 0
}}
>
{props.children}
</div>

Reload the page and click on Learn React, The modal should slide in.

Now let’s add a backdrop and when we click on the backdrop, it should dismiss the modal.

Now head over to your backdrop.js file, it is a simple component and doesn’t contain much, we just have to check if the show props is true then return a transparent div or null if false, likewise create a Backdrop.module.css, import it to the Backdrop.js file, your code should look like this

import React from 'react';
import classes from './Backdrop.module.css';

const Backdrop = (props) => (
props.show ? <div className={classes.Backdrop} ></div> : null
)

export default Backdrop

Now import the backdrop.js to the modal.js since they are closely connected, if the modal is shown, the backdrop should be shown

import Backdrop from '../Backdrop/Backdrop';

configure the show properties on the backdrop cause it is expected, and since we have the show properties available in the props we simply pass it to the Backdrop


const modal = props => {
return (
<>
<Backdrop show={props.show} />
....
</>
);
};

Now let’s make sure we can click this backdrop too, for that, we need to add a click listener on the backdrop.js on the div

const Backdrop = (props) => (
props.show ? <div className={classes.Backdrop} onClick={props.clicked}></div> : null
)

Let’s go back to the modal.js and provide a clicked property to trigger a function that will close the modal when clicked

const modal = props => {
return (
<>
<Backdrop show={props.show} clicked={props.modalClosed} />
.....
</>
);
};

modalClosed is now a property we have to add to the Modal property in our App.js file, head over to App.js and add modalClose property to the imported Modal

<Modal show={this.state.modalToggle} modalClosed={this.modalHandler}>

if you observe, the modalClose is set to trigger the modalHandler function, yes that is correct, i made a slight change the function to set modelToggle to the opposite of modelToggle

modalHandler = (e) => {
e.preventDefault();
this.setState({
modalToggle: !this.state.modalToggle
})
}

Now you have a working reusable modal with react

--

--

Infinitypaul

Software Developer — I admire breaking up complex problems into understandable and sizeable bits, solving daily challenges with technology