-
portals을 이용한 리액트 모달창(modal) 만들기Front-end/React 2021. 7. 6. 17:20반응형
(앞서 작성한 내용은 배움의 부족으로 나도 알아보기 애매해서... 다시 정리해서 올렸다.)
2021-10-22 수정 완료//
(궁금한 점이 있거나, 틀린 부분이 있으면 말씀주세요~~!🧸)
프로젝트의 기획이 바뀌면서 모달을 만들어야 할 일이 생겼다.
Modal은 리액트를 공부하다보면 한 번 쯤은 만들어보는 경우가 많이 있어서 간단하다고 생각했다.
그러나 공부를 할 때는 작동 방법에 대해서 배우느라 한 페이지에서 모달 창이 잠깐 나타나기만 하면 됐다.
하지만 프로젝트에서는 여러 곳에서 같은 Modal 창을 사용해야 한다.
그러면 단순히 component로 만들면 되지 않을까? 라고 생각 할 수 있지만 모달창은 의외로 복잡하다
(나만 그런가....)한 사이트의 글을 발췌해보면 아래와 같다.
"React's design and architectural best practices mean modal dialogs require more effort than throwing together a simple component."
대충 줄이자면 좋은 모달을 만들려면 생각보다 노력을 기울여야한다는 것이다.
물론 일일이 하드코딩으로 만드는 것도 한 방법이지만, 페이지 수가 많아지면 이 또한 고역이다.
그렇다면 좋은 리액트 모달을 만들기 위해서는 우리는 어떤 것을 생각해야 할까?
- 접근성을 위해서 DOM 본문 속성 끝에 모달을 추가해야한다. 하지만 리액트에서는 컴포넌트가 최상위 컴포넌트 내부에 마운트 되기 때문에 이는 사실 일반적이라고 할 수 없다.
- 모달이 DOM에 마운트 되고 보여질 때 까지 기다린다.
- "닫기"와 같은 모달 닫는 창을 닫았을 때 DOM에서 모달창이 사라져아한다.
- 모달을 나타내고 숨기는데 jQuery와 같은 라이브러리를 사용하여 DOM을 직접 조작하지 않는다
이를 위해서 portal이라는 것을 사용했다
모달을 나타내기 위해서 두 가지 정도의 컴포넌트가 필요하다.
첫 번째는 모달창을 보여주고 닫게 만드는 useModal.js 파일 그리고 두 번째는 useModal을 이용하여 만든 실제 모달창 이다
하나씩 살펴보자!
(여기서부터 대거 수정! 심플한 방식으로 설명해볼게요!!)
1. index.html에 새로운 div 태그를 만들자.
[ index.html ] <body> <div id="root"></div> <div id="modal"></div> </body>
리액트를 하면서 index.html을 열어본 분들이라면 기본적으로 "root" div 태그가 있는 것을 알고 있을 것이다.
이 root id를 가진 div 태그는 index.js에서 document.getElementById("root")로 사용하고 있다.
portals를 만들려는 이유 자체가 부모 컴포넌트의 종속을 받지 않기 위해서라는 이유도 있으므로 id가 modal이라는 새로운 div 태그를 만들어줬다.
2. Modal.jsx
html에 div 태그를 심어줬다면 Modal을 만들면 된다.
우선 만든 예시를 보자면 아래와 같다.
[ Modal.jsx ] import React from "react"; import ReactDOM from "react-dom"; const modalStyle = { position: "fixed", top: "50%", left: "50%", transform: "translate(-50%, -50%)", width: "600px", maxWidth: "100%", height: "400px", maxHeight: "100%", backgroundColor: "lightYellow", zIndex: "999" }; const overlayStyle = { position: "fixed", top: "0", left: "0", height: "100%", width: "100%", backgroundColor: "rgba(0, 0, 0, 0.8)", zIndex: "888" }; const Modal = ({ children }) => { return ReactDOM.createPortal( <> <div style={modalStyle}>{children}</div> <div style={overlayStyle}></div> </>, document.getElementById("modal") ); }; export default Modal;
이 글을 보는 분들이 사용 하시기 편하라고 CSS를 함께 넣어놓은 것이니 헷갈리지 않았으면 좋겠다.
일반적으로 modal을 만들면 뒷 배경을 blur 처리 하던지, 흑백으로 만들기 때문에 div 태그 2개를 만들어놓고, modal용 div에는 children을 넣어두었다.
그리고 중요한 것은 document.getElementById를 해서 아까 index.html에 넣어둔 modal이라는 id를 불러오는 것이다.
3. modal을 사용하고 싶은 곳.jsx
자, 이제 우리의 portals Modal을 사용하고 싶은 컴포넌트로 가자!
거기서 힘껏 만들어놨던 Modal을 import 해주면 된다.
import React, { useState } from "react"; import Modal from "./Modal"; const 모달사용하고싶은곳 = () => { return <Modal>이것이 모달이다!</Modal> }
이게 끝이다!
여기서 추가적으로 버튼을 만들어서 켜고 끄는 기능을 넣고 싶다면?
마지막 modal을 사용하고 싶은 곳.jsx로가서 useState를 불러온다.
그리고 modal을 열고 닫는 기능도 하나 만들어둔다.
그 예는 아래와 같다.
import React, { useState } from "react"; import Modal from "./Modal"; const 모달사용하고싶은곳 = () => { const [isOpen, setIsOpen] = useState(false); const modalOpen = () => { setIsOpen(!isOpen); }; return ( <button onClick={modalOpen}>모달 열기</button> <Modal> <h1>모달을 열면 이렇게 되요!</h1> <button onClick={modalOpen}>모달 닫기</button> </Modal> ) }
이렇게 해주면 켜고 끄는 버튼까지 함께 넣을 수 있을 것이다!
(Until Here)
이렇게 만드는 것은 간단한 버젼일 뿐이며, 선택에 따라서 Modal 자체를 생성하는 곳, On/Off Control 하는 곳, Modal 창을 보여주는 컴포넌트 등으로 세세하게 나눠서 할 수도 있으니 자신의 상황에 잘 맞춰서 만들어볼 수도 있다.
사실 이 외에도 React Modal libarary 등을 사용하는 방법도 있다.
더 쉽고 간단한 솔루션들이 있으니 필요에 따라서 사용을 하면 도움이 될 것이다!
반응형'Front-end > React' 카테고리의 다른 글
리액트 파일 업로드, 파일 다운로드 File upload, download with javascript react (2) 2022.06.24 React 상태 관리 : Recoil 로 해보자! (0) 2021.12.04 캘린더 날짜 바꾸기 - Welcome to Data structure (0) 2021.09.15 React - context API를 사용해보자! (0) 2021.09.07 리액트로 기간(날짜) 지정하기 date range ( react-flatpickr ) (0) 2021.07.05