리액트 프로젝트는 기본적으로 index.js에서 렌더링한다.

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <Router>
      **<App />**
    </Router>
  </React.StrictMode>,
);

reactDOM 라이브러리가 제공하는 reactRoot 함수가 반환하는 render 함수를 이용하는데, createRoot 함수는 인자로 먼저 `document.getElementById(”root”)`를 받는다.

여기서 id가 root인 HTML 요소는 `public/index.html`에 있다.

아래 html 파일이 개발서버를 구동했을 때 화면에 보이게 되는 html 파일이라고 볼 수 있다.

 

public/index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
  </head>
  <body>
    <div id="root"></div>
    **<div id="modal"></div>**
  </body>
</html>

root 페이지와 분리해서 만들기 위해 `id=”modal”`를 index.html에 만들어 뒀다.

 

 

 

CreatePortal 이란?

자식들을 DOM의 다른 부분으로 렌더링해주는 기능을 제공해준다.

createPortal – React

https://xionwcfm.tistory.com/316#google_vignette

 

src/components/Modal/ModalContainer.jsx

import { createPortal } from "react-dom";

function ModalContainer({ children }) {
  return createPortal(<>{children}</>, document.getElementById("modal"));
}

export default ModalContainer;

`createPortal(children, domNode, key?)`

  • 첫번째 인자: domNode의 children이 될 컴포넌트 혹은 jsx가 들어간다
  • 두번째 인자: children의 부모가 될 domNode를 넣어준다. index.html에 `<div id="modal"></div>`를 미리 만들어 뒀다.
  • 세번째 인자: 옵션인 키. 포털의 키로 고유한 문자열이나 숫자가 들어간다.
  • JSX에 포함될 수 있는 것이나 리액트 컴포넌트로 반환될 수 있는 React 노드를 반환한다.
  • 그래서 리액트가 렌더링 output에서 이를 발견하면 domNode안의 children을 출력한다!

 

src/components/Modal/index.jsx

import { useEffect } from "react";
import { useRef } from "react";
import styled from "styled-components";
import useOutsideClick from "hooks/useOutSideClick";
import ModalContainer from "./ModalContainer";

function Modal({ onClose, children }) {
  const modalRef = useRef(null);

  const handleClose = () => {
    onClose?.();
  };

  return (
    <ModalContainer>
      <Overlay>
        <ModalWrap ref={modalRef}>
          <Contents>{children}</Contents>
        </ModalWrap>
      </Overlay>
    </ModalContainer>
  );
}

export default Modal;

 

모달 닫고 끄는 로직은 useState를 이용!

state가 true일 땐 모달을 보여주고, false일 땐 모달을 보여주지 않는다.

 

HelpIcon눈에 띄는 색깔로 모달을 띄워 줄 글자(LRAT)를 강조하고, 사용자가 글자를 클릭하면 모달이 열린다.

→ LratModal.jsx가 랜딩된다

 

src/pages/Intro/MethodArea.jsx

import LratModal from "./LratModal";

function MethodArea() {
  const [isOpen, setIsOpen] = useState(false);

  const onOpen = () => {
    setIsOpen(true);
  };

  const onClose = () => {
    setIsOpen(false);
  };

  return (
    <Container>
      <SubTitle content="데이터 분석 방법" />

      <SubDesc>
        <span onClick={onOpen}>
          <HelpIcon /> LRAT (Lifestyle and Routine Activity Theories)
        </span>
        의 세 가지 요소를 개념화(operationalization)했습니다.
      </SubDesc>

      ...
      {isOpen && <LratModal onClose={onClose} />}
    </Container>
  );
}

export default MethodArea;

 

 

components 폴더에 만들어 둔 Modal을 import해서 모달 내용을 채운다.

‘확인’ 버튼이나 ‘X’ 아이콘을 클릭하면 모달이 닫힌다.

 

src/pages/Intro/LratModal.jsx

import styled from "styled-components";
import { Modal } from "components";
import { modalTree } from "assets/img";
import { MdClose } from "react-icons/md";

function LratModal({ onClose }) {
  return (
    <Modal onClose={onClose}>
      <CloseBtn onClick={onClose} />

      <Content>
        ...
      </Content>

      <Button onClick={onClose}>
        <p align="center">확인</p>
      </Button>
    </Modal>
  );
}

export default LratModal;

+ Recent posts