【React】Portal+Context+Hooks 로 모달 다이얼로그를 간단하게 취급

12763 단어 React후크

포털이란?


ReactDOM.createPortal() 는 컴퍼넌트 계층의 외부(=#root 와 같은 계층)의 DOM 요소에 컴퍼넌트를 렌더링 하는 메소드입니다.
이것에 의해 컴퍼넌트 계층에서의 z-index 를 신경쓰지 않고 모달 다이얼로그를 표시하는 것이 가능하게 됩니다.
개폐의 제어가 버킷 릴레이가 되는 것을 피하기 위해서, 기술을 간결하게 하기 위해서 Context 와 Hooks 를 이용해 가능한 한 간단하게 취급할 수 있는 모달 다이얼로그를 구현해 봅니다.
(알기 쉬운 모양을 위해 SemanticUI 를 사용하고 있으므로 실제로 실행하는 경우는 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css"/> 를 추가해 주세요)

구현



루트 노드



모달에 대한 루트 노드를 추가합니다.

index.html
<!-- 省略 -->
<div id="modal"></div>
<!-- 省略 -->

Context


useState() 에서 사용할 수 있는 형태로 Context 를 정의합니다.

isModalShown.js
import React from 'react';

export default React.createContext({
  isModalShown: false, // モーダル開閉ステータス
  toggleModalShown: () => {}, // ステータス更新関数
});


모달 다이얼로그 본체



Hooks를 사용하지 않는 경우와 비교하면 상당히 깔끔하게 쓸 수 있습니다.
제목과 텍스트는 props로 전달해야하지만 이번에는 생략합니다.

Modal.jsx
import React, { useContext } from 'react';
import ReactDOM from 'react-dom';
import isModalShown from '../contexts/isModalShown';

const Modal = () => {
  // 背景とCloseボタンのクリックで開閉ステータスをfalseにする
  const renderModal = modalHookState => {
    const [isModalShown, changeShownModal] = modalHookState;
    return (
      <div
        onClick={() => changeShownModal(false)}
        className="ui dimmer modals visible active"
      >
        <div
          onClick={e => e.stopPropagation()}
          className="ui standard modal visible active"
        >
          <div className="ui header">Modal Dialog</div>
          <div className="content">This is modal dialog with Context</div>
          <div className="actions">
            <button
              className="ui button primary"
              onClick={() => changeShownModal(false)}
            >
              Close
            </button>
          </div>
        </div>
      </div>
    );
  };

  // Contextの値を取得して開閉制御
  const modalHookState = useContext(isModalShown);
  return ReactDOM.createPortal(
    modalHookState[0] && renderModal(modalHookState),
    document.querySelector('#modal'),
  );
};

export default Modal;



모달을 부르는 측면의 구성 요소



모달 개폐 상태를 업데이트하는 함수를 onClick에 바인딩합니다.

CallModal.jsx
import React, { useContext } from 'react';
import isModalShown from '../contexts/isModalShown';
import Modal from './Modal';

const CallModal = () => {
  // Open Modalボタンクリックで開閉ステータスをtrueにする
  const renderCallModal = changeShownModal => {
    return (
      <div>
        <button onClick={() => changeShownModal(true)}>Open Modal</button>
      </div>
    );
  };

  return (
    <div>
      {renderCallModal(useContext(isModalShown)[1])}
      <Modal />
    </div>
  );
};

export default CallModal;



Provider



모달 개폐 상태와 Provider에서 변경할 함수를 전달합니다.

App.jsx
import React from 'react';
import isModalShown from '../contexts/isModalShown';
import CallModal from './CallModal';

const App = () => {
  // modalState...[isModalShown, toggleModalShown]
  const modalState = React.useState(false);
  return (
    <isModalShown.Provider value={modalState}>
      <CallModal />
    </isModalShown.Provider>
  );
};

export default App;



결과




버킷 릴레이를 피함으로써, Modal까지의 컴포넌트가 깊게 중첩했을 때의 재이용성이나 독립성을 높일 수 있었습니다.
표시/숨기기를 전환할 때는 반드시 Context의 값을 변경하면 되므로 취급하기 쉽다고 생각합니다.

참고 URL



htps : // Rea ctjs. rg / cs / 이렇게 xt. HTML
htps : // Rea ctjs. 오 rg / 드 cs / 호오 ks - 레페 렌세. HTML

좋은 웹페이지 즐겨찾기