<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="overlays"></div> 👈 모달과 백드롭을 포탈할 div
<div id="root"></div>
</body>
import React from "react";
import classes from "./Modal.module.css";
import ReactDOM from "react-dom";
const Backdrop = (props) => {
return <div className={classes.backdrop} onClick={props.onClose}></div>;
};
const ModalOverlay = (props) => {
return (
<div className={classes.modal}>
<div className={classes.content}>{props.children}</div>
</div>
);
};
const portalElement = document.getElementById("overlays");
const Modal = (props) => {
return (
<>
{ReactDOM.createPortal(<Backdrop />, portalElement)}
{ReactDOM.createPortal(
<ModalOverlay>{props.children}</ModalOverlay>,
portalElement
)}
</>
);
};
export default Modal;
const Cart = () => {
const cartitems = (
<ul className={classes["cart-items"]}>
{[{ id: "c1", name: "Sushi", amount: 2, price: 12.99 }].map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
return (
<Modal>
{cartitems}
<div className={classes.total}>
<span>Total Amount</span>
<span>35.62</span>
</div>
<div className={classes.actions}>
<button className={classes["button--alt"]}>Close</button>
<button className={classes.button}>Order</button>
</div>
</Modal>
);
};
DOM 트리의 어디서나 모달을 렌더링할 수 있다. Portal은 모달을 root DOM 노드가 아닌 다른 위치에 렌더링할 수 있도록 해줌. 이로 인해 모달의 스타일링 및 레이아웃을 더욱 세밀하게 제어할 수 있다.
모달이 다른 요소들과 겹쳐있을 때, 포커스 이슈를 해결할 수 있다. 모달이 다른 요소들과 겹쳐있을 때, 사용자가 포커스를 잃어버리는 문제가 발생할 수 있다. 하지만 Portal을 사용하면 모달이 root DOM 노드 밖에서 렌더링되므로 이러한 문제를 해결할 수 있다.
모달의 성능을 향상시킬 수 있다. React는 모든 컴포넌트가 렌더링될 때마다 가상 DOM을 재생성하고 다시 렌더링한다. 하지만 Portal을 사용하면 모달이 root DOM 노드 밖에서 렌더링되므로 성능이 향상될 수 있다.
코드의 가독성과 유지보수성을 향상시킬 수 있다. Portal을 사용하면 모달과 관련된 로직과 스타일을 별도의 파일로 분리할 수 있다. 이렇게 하면 코드의 가독성과 유지보수성이 향상되며, 컴포넌트 간의 의존성도 줄어들어 유연한 구조를 구성할 수 있다.
즉, 코드의 유연성과 가독성, 성능 등 다양한 이점을 가지고 있음.
interface LayoutProps {
title?: string;
canGoBack?: boolean;
hasTabBar?: boolean;
children: React.ReactNode;
}
객체 타입에서 일부 프로퍼티가 선택적이라는 것을 명시하는 방법
interface Person {
name: string;
age?: number;
}
위 인터페이스는 name 프로퍼티가 필수이지만 age 프로퍼티는 선택적이다. 따라서 아래의 두 객체는 모두 Person 타입에 할당될 수 있다.
const person1: Person = { name: 'Alice' };
const person2: Person = { name: 'Bob', age: 30 };
이러한 선택적 프로퍼티는 옵셔널한 인자를 받는 함수나 클래스 생성자 등에서 유용하게 사용될 수 있다. 함수의 인자를 선택적으로 받을 수 있게 하려면 인자 이름 뒤에 ?를 붙이면 됨. 예를 들어 다음 함수는 age 인자를 선택적으로 받는다.
function greet(name: string, age?: number) {
console.log(`Hello, ${name}!`);
if (age !== undefined) {
console.log(`You are ${age} years old.`);
}
}
age 인자가 생략될 경우 undefined 값이 할당되므로, 이를 검사하여 You are ${age} years old. 메시지를 출력하도록 구현.
이전 파이널 프로젝트는 이 문법을 몰라서 계속 프롭스타입으로 | undefined 같은 걸 적었는데 이런 편리한 문법이 있었다... 타입스크립트 조금 더 열심히 공부하고 프로젝트 들어갈 걸