Portal 및 Custom Hooks를 사용하는 단순하고 Typesafe React Modals

모달은 좋든 나쁘든 웹 애플리케이션에서 자주 요청되는 기능입니다. 나는 최근에 작동할 뿐만 아니라 feels OK 구현하는 React 애플리케이션에서 모달 상태와 배치를 관리할 수 있는 패턴을 발견했습니다. 사용자 정의 후크를 사용하면 상태 관리 라이브러리에 의존하지 않고 구성 요소 또는 애플리케이션 상태를 오염시키지 않고 모달 상태를 관리할 수 있습니다. React Portal을 사용하면 애플리케이션에서 원하는 곳에 구성 요소를 연결할 수 있습니다. 이 예제에서는 구성 요소를 구성 요소의 상위 범위에서 완전히 끌어올려 body 요소에 추가합니다.

useModal.ts


useModal.ts는 모달의 가시성을 관리하는 사용자 정의 후크입니다. 후크는 모달의 가시성과 이름이 의미하는 바를 정확히 수행하는 toggleVisibility 함수를 반환합니다.

import React from "react";

export const useModal = () => {
  const [modalIsVisible, setModalIsVisible] = React.useState(false);
  const toggleModalVisibility = () => setModalIsVisible(!modalIsVisible);

  return [modalIsVisible, toggleModalVisibility] as const;
};


모달.tsx


Modal.tsx는 모달 구성 요소입니다. 메모:
  • 사용자 정의 useModal 후크를 사용하면 모달 자체 내에서 모달의 상태에 액세스할 수 있으며 toggleVisibility 함수를 모달 UI에 전달하여 가시성을 토글할 수 있습니다.
  • ReactDOM.createPortal를 사용하면 모달 구성 요소를 상위 노드 범위 외부로 끌어올려 응용 프로그램의 body에 연결할 수 있습니다.

  • import React from "react";
    import ReactDOM from "react-dom";
    
    type ModalProps = {
      isVisible: boolean;
      toggleVisibility: () => void;
      modalContent: React.ReactNode;
    };
    
    export const Modal = ({
      isVisible,
      toggleVisibility,
    
    }: Readonly<ModalProps>): JSX.Element | null => {
      const modal: JSX.Element = (
        <>
          <div className="backdrop" onClick={toggleVisibility} />
          <div className="modal" aria-modal aria-label="Modal Details" role="dialog">
            {modalContent}
    
            <span
              className="modal-close"
              aria-label="Close Modal Details"
              onClick={toggleVisibility}
            >
              &times;
            </span>
          </div>
        </>
      );
    
      return isVisible ? ReactDOM.createPortal(modal, document.body) : null;
    };
    


    모달 스타일.css



    CSS는 모달을 올바르게 표시하는 데 필요합니다. 스타일은 응용 프로그램에 따라 매우 다르지만 일반적으로 오른쪽 상단 모서리에 있는 고정 위치와 닫기 버튼으로 시작합니다.

    .backdrop {
      background-color: rgba(255, 255, 255, 0.6);
      bottom: 0;
      left: 0;
      position: fixed;
      right: 0;
      top: 0;
    }
    
    .modal {
      --var-rhythm: 1.8rem;
    
      align-items: center;
      background-color: white;
      border: 1px solid gray;
      border-radius: 6px;
      display: flex;
      flex-direction: column;
      justify-content: center;
      left: 50%;
      max-width: calc(100vw - var(--rhythm));
      max-height: calc(100vh - var(--rhythm));
      min-width: 300px;
      padding: calc(var(--rhythm) * 2) calc(var(--rhythm) * 2) var(--rhythm);
      position: fixed;
      text-align: center;
      top: 50%;
      transform: translate(-50%, -50%);
      overflow-y: scroll;
    }
    
    @media (min-width: 600px) {
      .modal {
        min-width: 600px;
      }
    }
    
    .modal > * {
      margin: 0;
      margin-bottom: var(--rhythm);
    }
    
    .modal-close {
      color: gray;
      cursor: pointer;
      font-size: 2rem;
      line-height: 1rem;
      padding: 0;
      position: absolute;
      right: calc(var(--rhythm) / 2);
      top: calc(var(--rhythm) / 2);
    }
    


    구성요소.tsx



    이제 모달을 사용하는 데 필요한 모든 것은 후크를 가져오고Modal.tsx 애플리케이션에서 필요한 곳이면 어디든지 가져오는 것입니다.

    import { Modal } from "../components/Modal";
    import { useModal } from "../../hooks/useModal";
    
    export const Component = (): JSX.Element => {
      const [modalIsVisible, toggleModalVisibility] = useModal();
      const modalContent: React.ReactNode = (<p>This goes in the modal.</p>);
    
      return (
        <Modal
          isVisible={modalIsVisible}
          toggleVisibility={toggleModalVisibility}
          modalContent={modalContent}
        />
      )
    };
    


    즐거운 모달 만들기 ಠ_ಠ! 구현을 위한 더 나은 패턴이 있다면 학교 교육을 받고 싶습니다... 계속 배우십시오!

    좋은 웹페이지 즐겨찾기