Creating a Modal Component: The Redux Way
You know what? I think I’m in love. I can’t seem to get enough of Bootstrap 4! 😊
However, as much as I love Bootstrap 4, there are times I don’t want to use all of its components or classes. I might want to create my own Bootstrap theme and forgo all of the JS components.
A short story…
So I began creating my components the React way….and alas! I realised I needed a modal! Crap, I didn’t forsee that. I’m using Redux, I’m stuck and don’t know how to create a modal. Do I have to write jQuery?
Quick answer: No, you don’t 💥.
The above was a scenario I encountered some days ago. Google and I had a very long discussion and we finally agreed that the Redux approach was the best way to create a modal component in React. I mean, it’s just smooth.
Don’t panic. It’s quite straight forward. Let’s take a quick dive.
Setup Project
Setup your React project like you normally would. For this little experiment, I setup the project using create-react-app. Run the following command:
npx create-react-app redux-modal-component
cd redux-modal-component
Setup Redux
I wrote a tutorial on setting up Redux with create-react-app (CRA).
Creating the Modal
We’ll need two major packages for our badass component: react-modal
— for modal accessibility — and bootstrap
— for styling.
npm install react-modal --save
npm install bootstrap --save
Modal Actions
- Define redux action types: For this project I used keymirror.
npm install keymirror --save
In constants
folder, create an ActionTypes.js
file and define your modal action types. Basically, you want to show and hide your modal.
- Create the Redux action creators
To make the modal component reusable and dynamic, we’ll define modalProps
and modalType
parameters. modalProps
will be an object of modal properties (e.g title, message, button click functions, etc) and modalType
will be a string specifying the type of modal (e.g confirm, prompt, delete, etc).
Modal Reducer
Here we define how the application state changes with respect to the modal action triggered.
Modal Types
Now, these will just be presentational components. Define them in src/components/Modals/
. Here’s an example:
Create other modal components: depending on your design pattern, you could have just one component that renders different modals with respect to the props given.
The ModalRoot
This is the modal container component and it will be called just once — in the entry file. It will also be connected to the redux store. This would allow it access modal props in state.
Activate Modal
In App.js
, import the modal actions and connect the component to the redux store. Why? — we want to dispatch our modal actions.
const mapDispatchToProps = dispatch => ({
hideModal: () => dispatch(hideModal()),
showModal: (modalProps, modalType) => {
dispatch(showModal({ modalProps, modalType }))
}
})
- Add a button component and set an
onClick
function:
<button
className="btn btn-outline-primary btn-block"
onClick={this.openAlertModal}
>alert</button>
- Define the
onClick
function:
openAlertModal(event) {
this.props.showModal({
open: true,
title: 'Alert Modal',
message: MESSAGE,
closeModal: this.closeModal
}, 'alert')
}
- Start the project. Run
npm start
in your terminal (your project should be running on port 3000). Click on the button displayed. Your modal should look like this:
Now, let’s add our Bootstrap classes.
- React-modal is very customisable, hence we can add Bootstrap classes. It has props which can be used to define these classes. Add the following props to
<ReactModal />
component:
overlayClassName="modal fade show"
bodyOpenClassName="modal-open"
className="modal-dialog modal-dialog-centered"
- Import your modal types in ModalRoot and display the modalType specified in props:
Start the project, click on the button and see our modal appear 😄
Conclusion
The coolest thing about this approach is that the modal component is not imported in every instance it’s being called. It’s only called once — in the entry file. All that is required is to call the modal function and voilà! Importing the modal component in every instance it’s called is also fine but I prefer this approach better. It’s neater.
What are your thoughts on this approach? Let’s discuss. And yeah, I created a Github repo for this experiment too 😉. Cheers!