DEV Community

Cover image for Criando um Modal em ReactJS
Renato Hideki Osaka
Renato Hideki Osaka

Posted on

Criando um Modal em ReactJS

Preciso de uma janela modal em meu sistema ou site e agora o que fazer? Desenvolver o meu próprio componente ou instalar uma biblioteca inteira só para usar um simples modal?

Muitos escolhem a segunda opção, as vezes pela facilidade de estar pronto, outros por falta de conhecimento para desenvolver o próprio componente. Então decidi compartilhar com vocês um simples exemplo em ReactJS.

import React, { useState, useEffect } from 'react'
import ReactFrom from 'react-dom'

import './modal.css'

import React, { useState, useEffect } from 'react'
import ReactDom from 'react-dom'

import './modal.css'

interface ModalProps {
  isShowing: boolean;
  toggle: () => void;
}

const Modal: React.FC<ModalProps> = ({ isShowing, toggle, children }) => { 
  useEffect(() => {
    const listner = function (e: KeyboardEvent ) {
      if (e.key === 'Escape' || e.key === 'Esc' || e.keyCode === 27) {
        e.preventDefault();
        e.stopPropagation();

        isShowing && toggle();
      }
    }

    window.addEventListener('keyup', listner)

    return (() => {
      window.removeEventListener('keyup', listner)
    })

  }, [isShowing, toggle])

  return (
    isShowing ? ReactDom.createPortal(
      <div className="modal-overlay">
        <div className="modal-wrapper">
          <div className="modal">
            {children}
          </div>
        </div>
      </div>, document.body
    ) : null
  )
}

interface ModalHeaderProps {
  toggle: () => void;
}

export const ModalHeader: React.FC<ModalHeaderProps> = ({ toggle, children }) => (
    <div className="modal-header">
        {children || 'Title'}
    <button 
            className="modal-button-close" 
            data-dismiss="modal" 
            aria-label="Close" 
        onClick={toggle}
    >
      &times;
    </button>    
    </div>
)

export const ModalBody: React.FC = ({ children }) => (
    <div className="modal-body">
        {children}
    </div>
)

export const ModalFooter: React.FC = ({ children }) => (
    <div className="modal-footer">
        {children}
  </div>
)

export const useModal = () => {
  const [isShowing, setIsShowing] = useState(false);

  function toggle() {
    setIsShowing(!isShowing);
  }

  return {
    isShowing,
    toggle,
  }
}

export default Modal;
Enter fullscreen mode Exit fullscreen mode
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1040;
  width: 100vw;
  height: 100vh;
  background-color: rgba(0,0,0,0.5);
}

.modal-wrapper {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1050;
  width: 100%;
  height: 100%;
  overflow-x: hidden;
  overflow-y: auto;
  outline: 0;
}

.modal {
  z-index: 100;
  background: white;
  position: relative;
  margin:20px auto;
  border-radius: 3px;
  max-width: 800px;
  padding: 8px;
  border-radius: 4px;
}

.modal-header {
  display: flex;
  justify-content: space-between;
  border-bottom: 1px solid #ddd;
  padding: 8px 0;
  font-weight: bold;
}

.modal-button-close {
  background: transparent;
  border: none;
  cursor: pointer;
  font-size: 16px;
}

.modal-body {
  padding: 8px 0;
}

.modal-footer {
  display: flex;
  flex-direction: row;
  justify-content: flex-end;
  padding: 8px 0;  
}
Enter fullscreen mode Exit fullscreen mode

Agora para usar o componente criado é simples

import React from 'react';
import Modal, {
    ModalHeader, 
    ModalBody, 
    ModalFooter, 
    useModal
} from './components/Modal'

function App() {
  const { isShowing, toggle } = useModal();

  return (
    <div>
      <button onClick={toggle}>
        Modal 
      </button>

      <Modal {...{isShowing, toggle}}>
        <ModalHeader {...{toggle}}>
          My Title
        </ModalHeader>
        <ModalBody>
          Hello World!
        </ModalBody>
        <ModalFooter>
          <button onClick={toggle}>
            Cancel
          </button>
        </ModalFooter>        
      </Modal>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Exemplo

Link do github https://github.com/renatoosaka/useModal

Top comments (1)

Collapse
 
naiaraborges profile image
Naiara Borges

Gostei muito do seu modelo utilizei ele e na minha página tive várias modais, só que quando clico nela aparece todas de uma vez, como faço para deixar apenas 1 por vez? Obrigada