return (
<>
<Modal />
<InputForm />
</>
);
위 컴포넌트를 예를 들어보면, 실제 DOM에 들어가는 내용은 아래와 같을 것이다.
<section>
<div className='backdrop' />
<div className='modal'>
<div className='content'>
<p>{props.message}</p>
</div>
</div>
<form>
...
</form>
</section>
이 코드는 잘 동작하지만 의미적인 관점에서 좋지 않다.
모달은 전체 페이지 위에 표시되는 오버레이이다. 따라서 다른 모든 것 위에 있어야 하는 것이 맞다.
하지만 이 코드는 다른 HTML 코드 안에 중첩되어 있기 때문에 좋은 코드가 아니다.
따라서 모달이 깊게 중첩되지 않게, 다른 것들 위에 있어야 하려면 다음과 같은 구조가 맞다.
<div className='backdrop' />
<div className='modal'>
<div className='content'>
<p>{props.message}</p>
</div>
</div>
<section>
<form>
...
</form>
</section>
이처럼 렌더링하려는 HTML 내용을 다른 곳으로 이동시켜 렌더링하려면 Portal을 사용하면 된다.
Portal
1. 컴포넌트를 이동시킬 장소 필요
보통 public/index.html 에서 div를 추가해 나중에 이 장소를 찾아오도록 한다.
루트를 여러 개 만들어서 여러 다른 종류의 컴포넌트들을 해당 div로 이동시킬 수 있다.
2. 리액트에게 실제로 어딘가로 포탈되어야 한다고 알려준다.
createPortal 메서드는 react-dom 라이브러리에 정의되어 있다.
import { createPortal } from 'react-dom';
or
import ReactDOM from 'react-dom';
// 사용-> ReactDOM.createPortal
createPortal의 인수로는 렌더링할 리액트 노드를 전달해주고(JSX여야 한다.),
두 번째 인수로는 첫 번째 인수의 컴포넌트가 렌더링되어야 하는 DOM의 컨테이너를 가리키는 포인터(DOM 노드)를 전달해주면 된다.
const Modal = (props) => {
return (
<React.Fragment>
{ReactDOM.createPortal(
<Backdrop onConfirm={props.onConfirm} />,
document.getElementById('backdrop-root')
)}
{ReactDOM.createPortal(
<ModalOverlay
title={props.title}
message={props.message}
onConfirm={props.onConfirm}
/>,
document.getElementById('overlay-root')
)}
</React.Fragment>
);
};
export default Modal;
createPortal을 사용해 렌더링된 HTML 내용을 다른 곳으로 이동시킨다.
'React' 카테고리의 다른 글
[React] useReducer (0) | 2023.09.14 |
---|---|
[React] useEffect (0) | 2023.09.14 |
[React] JSX limitation, Fragment (0) | 2023.09.13 |
CSS Module (0) | 2023.09.11 |
styled-components (0) | 2023.09.11 |