DEV Community

Omar Elwakeel
Omar Elwakeel

Posted on

Want to open modals from any place in your code? this article is for you!

When I was a beginner developer, I struggled with opening and closing modals, the UI itself was no issue, but managing the state of the application modals was a trouble, if you feel or ever felt the same, go through this simple and short tutorial, I will give you a guide on how to make it better.

Requirements

  • SPA (react, vue, ...) or SSR (next, nuxt, ...)

  • Application state management tool (redux, ...)

  • Modal design or a ready one like MUI's modals

For this tutorial, I'm going to use react, redux and MUI's modal

Enough with the intro, let's start some code

I suppose you will have a layout that wraps your code, assume this is the content of it

<div>
 <Navbar />
 {children} // these are the actual page content
 <Footer />
</div>
Enter fullscreen mode Exit fullscreen mode

To have a central modal to be managed from everywhere in the code you should have a central state, in my case it's redux

ModalState {
 isOpened: boolean;
 current: "auth-modal" | "checkout-modal" | "confirm-modal";
 args: any;
}
Enter fullscreen mode Exit fullscreen mode

isOpened is a boolean to check if the modal is currently opened

ModalType is a string that identifies the current modal to be rendered

args is any kind of arguments you want to send to the current modal

Inside the modal state slice

openModalAction: (state, action) => {
 const { current, args } = action.payload;
 return {
  isOpened: true,
  current,
  args
 }
},

closeModalAction: (state, action) => {
 return {
  ...state,
  isOpened: false,
  args: []
  }
 }
Enter fullscreen mode Exit fullscreen mode

openModalAction sets the current modal and sends the required props to that modal through the args parameter

closeModalAction closes the modal opened no matter any

Going back to the layout that is wrapping the whole app you can add one more component

<div>
 <Navbar />
 {children} // these are the actual page content
 <Footer />
 <CentralModalRenderer />
</div>
Enter fullscreen mode Exit fullscreen mode

for the CentralModalRenderer component, it can be like the following

const dispatch = useDispatch();
const { current, isOpened, args } = useSelector((state) => state.modal)

function renderCurrentComponent() {
    switch (current) {
        case "auth-modal":
            return (<AuthModal {...args} />)
                case "checkout-modal":
            return (<CheckoutModal {...args} />)
        default:
            return null
    }
}

const handleClose = () => {
 dispatch(closeModalAction())
}

return (
    isOpened ? (
        <Modal 
                     open={isOpened} 
                     handleClose={handleClose}
                 >
            {renderCurrentComponent()}
                 <Modal/>
        ) : null
    )
Enter fullscreen mode Exit fullscreen mode

Modal is MUI's modal, that requires two props, boolean to for the modal to be opened or not, and on close handler

isOpened whenever true will open the modal state

renderCurrentComponent is a function to check which is the current value in the modal state and renders the modal component created that matches

Notice that the args are always sent to the component, so how to open it, easy

<button
onClick={() => dispatch(openModal({current:"auth-modal", args:{message:"Are you sure you want to leave?"}}))}
>
open modal
</button>
Enter fullscreen mode Exit fullscreen mode

I hope this was enough to start your own central modal, the same idea can be used to implement a central notification system, or a central management state for UI, all over your code and components

Top comments (0)