DEV Community

Discussion on: React: Using native dialogs to make a modal popup

Collapse
 
link2twenty profile image
Andrew Bone

The documentation I read on mdn didn't mention the close method so I, foolishly, just accepted there wasn't one. The documentation you linked is a lot more thorough thank you. I've updated my post.

Yes if you support anything older than cutting edge you're going to need either a polyfill or to keep using the old method for now (which is why I linked my old post too).

Collapse
 
tbroyer profile image
Thomas Broyer • Edited

Fwiw, here's our 3 year old component (at the time, only Chrome supported the element natively):

const Modal = ({ children, header, closeModal, visible }) => {
  const container = useRef(null);
  if (container.current == null) {
    container.current = document.createElement("div");
  }

  const dialog = useRef(null);

  useEffect(() => {
    document.body.appendChild(container.current);
    return () => container.current.remove();
  }, []);

  useEffect(() => {
    if (dialog.current) {
      dialogPolyfill.registerDialog(dialog.current);
    }
  });

  useEffect(() => {
    if (dialog.current) {
      if (visible) {
        // without this test, hot reload will error out when the modal is still visible
        if (!dialog.current.open) {
          dialog.current.showModal();
        }
      } else {
        dialog.current.close();
      }
    }
  }, [visible]);

  return createPortal(
    !visible ? null : (
      <dialog
        className={styles.modal_container}
        ref={dialog}
        onCancel={e => {
          e.preventDefault();
          closeModal && closeModal(e);
        }}
      >
        <div className={styles.modal_header}>
          {header}

          {closeModal && (
            <button className={styles.modal_close} onClick={closeModal}>
              <Icon icon="close-circle" />
            </button>
          )}
        </div>

        <div className={styles.modal_content}>{children}</div>
      </dialog>
    ),
    container.current,
  );
}
Enter fullscreen mode Exit fullscreen mode