React Portal

최문경·2022년 1월 15일
0

사용자가 form에서 잘못된 제출을 했을 때 modal을 띄워주는 컴포넌트를 만들어보자.

import Card from './Card';
import Button from './Button';
import classes from './ErrorModal.module.css';

const ErrorModal = (props) => {
  return (
    <div>
      <div className={classes.backdrop} onClick={props.onConfirm} />
      <Card className={classes.modal}>
        <header className={classes.header}>
          <h2>{props.title}</h2>
        </header>
        <div className={classes.content}>
          <p>{props.message}</p>
        </div>
        <footer className={classes.actions}>
          <Button onClick={props.onConfirm}>Okay</Button>
        </footer>
      </Card>
    </div>
  );
};

export default ErrorModal;

위의 코드가 잘못됐다고는 할 수 없다. 하지만 이상적인 코드가 아닌 것은 분명하다. 왜냐하면 modal은 페이지 전체를 덮기 때문에 가장 바깥에 있는 것이 구조적으로는 맞기 때문이다.

이러한 상황에서 저 모달을 가장 바깥으로 즉, 원하는 위치로 보낼 수 있는 기능을 가진 것이 createPortal 메서드이다.

ReactDOM.createPortal(child, container);

createPortal 메서드를 사용해 수정하면 아래와 같다.

import React from 'react';
import ReactDOM from 'react-dom';
import Card from './Card';
import Button from './Button';
import classes from './ErrorModal.module.css';

const Backdrop = (props) => {
  return <div className={classes.backdrop} onClick={props.onConfirm} />;
};

const Overlay = (props) => {
  return (
    <Card className={classes.modal}>
      <header className={classes.header}>
        <h2>{props.title}</h2>
      </header>
      <div className={classes.content}>
        <p>{props.message}</p>
      </div>
      <footer className={classes.actions}>
        <Button onClick={props.onConfirm}>Okay</Button>
      </footer>
    </Card>
  );
};

const ErrorModal = (props) => {
  return (
    <>
      {ReactDOM.createPortal(
        <Backdrop onConfirm={props.onConfirm} />,
        document.getElementById('backdrop')
      )}
      {ReactDOM.createPortal(
        <Overlay
          title={props.title}
          message={props.message}
          onConfirm={props.onConfirm}
        />,
        document.getElementById('overlay')
      )}
    </>
  );
};

export default ErrorModal;
profile
프론트엔드 공부하고 있습니다!

0개의 댓글