모달은 어디에 넣어야 할까?
사실 퍼블리셔로 시작한 나로써는 최적화적인 면도 중요하지만 DOM 의 구조를 잘 파악하고 체계적이고 직관적인 구조로 짜는것이 가장 베스트의 코드라 생각한다. 특히나 모달의 경우는 머리로는 구현이 쉽지만 상태 모달부터 시작해 기능과 submit 모달 등등 다양한 기능을 가지고 있다. 실시간으로 뿜어져나오는 여러 모달을 처리하기엔 최적화적인 코드를 사용하고싶지만 그것도 쉽지않다.
구조적으로 하위 내용과 div 로 감싸진 곳에선 모달을 사용하지 않는 편이 좋다. css 코드를 만지다보면 가끔 z-index 를 무작위로 사용하는 경우가 많은데 이 점을 고려하지 않고 모달작업을 하면 상위 position에 맞춰 모달이 본인에 위치를 잃어버린다. 하위에서 아무리 z-index 를 우겨넣어봤다. 반영되지 않는다. 그래서 기존에 모달은 가장 상위 <body> 바로 밑에 따로 코드로 남겨놓는것이 좋다.
vue 의 경우 코드형식이 html 과 매우 흡사한 구조로 작업하면 되서 모달의 위치를 상단으로 빼놓고 작업하는 경우가 많았지만 react처럼 컴포넌트 단위로 코드를 짤 땐 모달은 꽤 골치아픈 존재였다 (내가 초보이기 때문에 더 그럴수도)
이때 강의에서 들은게 바로 포탈이였다. React-dom 에서 제공해주는 createPortal 을 사용하면 id 로 선언된 public 파일 안에 모달을 우겨넣을 수 있다. ㅎㅎ (렌더링되는 실제 jsx 파일에선 전부 이동이 가능하며, 불필요한 dom 요소를 줄여 효율적인 렌더링이 가능해진다 )
> public > index.html
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="overlay-root"></div>
<div id="backdrop-root"></div>
<div id="root"></div>
</body>
> Modal.js
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}></div>;
};
const ModalOverlay = (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 (
<React.Fragment> //<></> 로 축약해서 사용가능
{ReactDOM.createPortal(
<Backdrop onClick={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 ErrorModal;
> ReactDOM.createPortal( 넣어줄 dom 요소 , id 요소 )
ReactDOM.createPortal( <ModalOverlay title={props.title} message={props.message} onConfirm={props.onConfirm} />, document.getElementById("overlay-root") )
'쬬의 React' 카테고리의 다른 글
[React] next-i18next error / i18next Text content did not match. Server: "introMessage" Client: (0) | 2023.06.28 |
---|---|
[React] useEffect 와 CleanUp 작동방식 이해하기 + input 입력완료 후 감지 코드예시 (0) | 2023.04.09 |
[React] 렌더링 상태 체크하기 (크롬 익스텐션 활용) (0) | 2023.04.09 |
[React] input 상태 업데이트 useState,useRef (0) | 2023.04.08 |
[React] 클릭(click)이벤트 기초정리 (0) | 2022.12.04 |