Create Modal with React Portal and React Hooks from scratch without external library

Let's take a quick look at final output :


Modal.js File , which contains modal view and its content along with a close button

import React from 'react'
import './style.css'
const Modal = ({open,close,modalText}) =>{
    const classModal = open ? "modal--open" : "modal--close"

    return(
        <div className={classModal}>
            <div className="modal">
                <span className="close" onClick={close}>X</span>
                <span className="modalText">{modalText}</span>
            </div>
        </div>
    )
}

export default Modal
style.css file used in above file

.modal{
    padding: 12px;
    background: blue;
    width: 320px;
    text-align: center;
}
@keyframes fadeIn {
    from { opacity: 0; }
      to { opacity: 1; }
}
@keyframes fadeOut {
    from { opacity: 1; }
      to { opacity: 0; }
}
.modal--close,.modal--open{
    position: fixed;
    display: none;
    justify-content: center;
    align-items: center;
    top: 0;
    left: 0;
    width: 100vw;
    height: 50vh;
    animation: fadeOut 1s;
}
.modal--open{
    display: flex;
    animation: fadeIn 1.5s;
}
.close{
    cursor: pointer;
    display: block;
    background: gray;
    width: 50px;
    float: right;
}
.modal span{
    color: white;
    font-size: 20px;
}
.modalText{
    width: 100%;
    display: inline-block;
}

We will use a Modal Wrapper for above which will create a separate node in the DOM tree for rendering the modal

import React, { useEffect } from 'react'
import ReactDOM from 'react-dom'
import Modal from './Modal'
let node = null
const ModalWrapper = (props) =>{
    useEffect(()=>{
        node && ReactDOM.render(<Modal {...props} />,node)
    })
    useEffect(()=>{
        node = document.createElement('div')
        document.body.appendChild(node)
        ReactDOM.render(<Modal {...props} />,node)
    },[])
    return(
        <script />
    )
}
export default ModalWrapper

Now in the App.js component we will use the wrapper, and set properties for opening and closing the modal

import React, { Fragment, useState } from 'react';
import ModalWrapper from './components/ModalWrapper'
const App = () => {
  const [open,setOpen] = useState(false)
  const openModal = _ => {
    setOpen(true)
  }
  const onCloseModal = () =>{
    setOpen(false)
  }
  return (
    <Fragment>
      <button style={{
        width: 100,
        height: 40,
        color: 'black',
        background: 'lightblue',
        fontSize: 20,
      }} onClick={openModal}>Click Me</button>
      <ModalWrapper open={open} modalText="Modal using React Portal by " 
      close={onCloseModal} />
      <a style={{
        display:'block',
        fontSize:15,
        paddingTop:20
      }} href="https://reactcodes.blogspot.com/">
      https://reactcodes.blogspot.com/</a>
    </Fragment>
  );
}
export default App;


As you can see in the below picture of DOM tree for the current app, the modal is being rendered outside of 'root' element



Thanks for your time  :)

Comments

  1. Thank you for sharing such a useful article. It will be useful to those who are looking for knowledge. Continue to share your knowledge with others through posts like these, and keep posting.

    Poker Game App Development Company

    ReplyDelete

Post a Comment

Popular posts from this blog

Best coding practice and structure for redux saga with react hooks | Separate watcher and worker saga | React clean code

How to use redux with React Hooks - Creating TodoList

Setting up Redux Devtools for React applications