JSX는 기본적으로 여러 요소들을 같이 사용할 경우 이들을 감싸주는 요소가 필요합니다.
이때 "div" 태그를 사용해서 wrapping 해주면 다음과 같은 문제점이 발생 합니다.
그래서 이를 위한 해결 방법으로는 다음과 같은 방법들이 있습니다.
장점으로는 짧고 간편합니다, 그리고 실제 HTML요소를 DOM에 렌더링하지 않는다.
하지만 프로젝트 설정에 따라 다르기 때문에 빌드 워크플로가 이를 지원 해야 사용할 수 있다.
<>
<div>HI</div>
<div>HIII</div>
</>
이것도 마찬가지로 실제 HTML요소를 DOM에 렌더링 하지 않는다.
그리고 리액트에 내장되어 있기 때문에 항상 사용할 수 있다.
사용 방법은 Fragment를 따로 임포트해서 사용하거나 React.Fragment를 사용하면 된다.
<React.Fragment>
<div>HI</div>
<div>HIII</div>
</React.Fragment>
Wrapper 컴포넌트를 따로 만들어서 사용 해도 DOM에 영향을 주지 않는다.
다음과 같이 작성하면 빈껍데기에 하위 요소를 렌더링 해주는거기 때문에 위에 두 방법과 동일하다.
const Wrapper = props => {
return {props.children}
}
export default Wrapper
<Wrapper>
<div>HI</div>
<div>HIII</div>
</Wrapper>
이전 포스팅에서 모달을 구현할때 위와 같은 방식으로 구현 하였는데 이때 스타일링을 통해서 동작은 잘하지만 구조적으로 봤을때 문제점이 생긴다.
우선 모달은 오버레이이다.
오버레이는 전체 페이지 위에 표시되는 것을 말하는데 위와 같이 구현 했을때 다른 HTML 코드 안에 중첩 되어 렌더링 되기 때문에 스타일링을 통해 작동은 할지 몰라도 좋은 구조를 가지는 것은 아니다, 그리고 스크린 리더가 HTML 코드를 해석할 때 일반적인 오버레이로 인식하지 못 할 수도 있다.
또한 이것은 HTML 코드 안 깊은 곳에 자리 잡고 있기 때문에 다른 모든 내용에 대한 오버레이인지 명확하지 않다.
이를 위한 해결 방법으로는 리액트의 포털을 사용하면 된다.
ReactDOM.createPortal은 렌더링될 HTML 내용을 지정해둔 포인터로 옮겨 주기 때문에 오버레이를 사용할때 사용하면 좋다.
이때 렌더링 되어야 하는 리액트 노드(반드시 JSX),DOM 엘리먼트
<body>
<div id="backdrop-root"></div>
<div id="overlay-root"></div>
<div id="root"></div>
</body>
import ReactDom from "react-dom"
import React from "react";
import ReactDOM from "react-dom";
import Button from "../UI/Button";
import Card from "../UI/Card";
import styles from "./Modal.module.css";
const Backdrop = ({ onCloseModal }) => {
return <div className={styles.backdrop} onClick={onCloseModal}></div>;
};
const ModalOverlay = ({ onCloseModal, message, title }) => {
return (
<Card className={styles.modal}>
<h2 className={styles.head}>{title}</h2>
<div className={styles.content}>{message}</div>
<div className={styles.control}>
<Button type="button" onClick={onCloseModal}>
Okay
</Button>
</div>
</Card>
);
};
JSX안에서 사용되기 때문에 {}를 사용해준다.
const ErrorModal = ({ onCloseModal, message, title }) => {
return (
<React.Fragment>
{ReactDOM.createPortal(
<Backdrop onCloseModal={onCloseModal} />,
document.getElementById("backdrop-root")
)}
{ReactDOM.createPortal(
<ModalOverlay
onCloseModal={onCloseModal}
title={title}
message={message}
/>,
document.getElementById("backdrop-root")
)}
</React.Fragment>
);
};
export default ErrorModal;