알림창을 띄울 때, 로그인 등 입력값을 받아야할 때 등 여러 상황에서 자주 쓰이는 모달을 구현해보고자 합니다.
1. modal component
'open modal' 버튼에 onClick 이벤트를 적용하고, 버튼을 클릭하면 showModal 값이 true로 바뀌도록 상태관리를 해줍니다. showModal이 true가 되면 Modal이 등장하겠죠?
const [showModal, setShowModal] = useState(false);
const onShowModal = () => {
setShowModal(true);
};
const onHideModal = () => {
setShowModal(false);
};
return (
<div className={styles.container}>
<button className={styles.modalButton} onClick={onShowModal}>
Open Modal
</button>
{showModal && <div className={styles.modal}>
<div className={styles.box}>
<button onClick={onHideModal}>x</button>
<span>HELLO WORLD</span>
</div>
</div>}
</div>
);
2. CSS
모달이 열리도록 했으니, css를 적용해야 합니다. 부모클래스의 position은 relative로 주고, 자식 클래스 position은 absolute로 하면 부모의 영역 안에서 자식의 위치를 top, left, right, bottom값으로 조정할 수 있습니다.
modal처럼 부모클래스의 영역을 전부 이용하고 싶다면 width, height를 모두 100%로 설정하면 됩니다.
.container {
border: 1px solid grey;
position: relative;
width: 100%;
height: 100vh;
}
.modal {
width: 100%;
height: 100%;
background-color: #00000080;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
border-radius: 8px;
}
.box {
width: 50%;
height: 50%;
background-color: white;
border-radius: 10px;
}
3. modal 바깥을 클릭 했을 때 닫히도록 만들고 싶다면? 이벤트 버블링 차단하는 메소드 사용하기
1) 모달이 열린 상태에서 클릭 이벤트가 일어났을 때 그 영역이 어디인지 확인하고, 만약 모달 바깥이라면 닫히도록 하는 방법과, 2) event.stopPropagation()을 이용해 간단하게 처리하는 방법이 있습니다. (참고 : https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation)
첫번째 방법은 전역에서 클릭이벤트가 발생하는 것을 감지해야 하므로, 비효율적으로 생각되어 두번째 방법을 이용했어요.
stopPropagation외에도 stopImmediatePropagation(https://developer.mozilla.org/en-US/docs/Web/API/Event/stopImmediatePropagation)를 사용할 수 있는데요.
주의할 점은 stopPropagation은 상위의 모든 이벤트 버블링을 차단하지만, stopImmediatePropagation은 같은 레벨의 다른 모든 이벤트도 동작하지 않도록 차단한다는 것이예요. 둘의 차이점을 알고 적절하게 사용하면 좋을 것 같네요.
아래처럼 부모요소에는 modal을 닫는 함수를 걸고,
자식요소에서 이벤트 버블링을 차단한다면 shadow처리되는 영역을 클릭했을 때 모달이 닫히게 됩니다.
<div onClick={() => onHideModal()}>
<div onClick={(e) => e.stopPropagation()}>
<div>
<span>{title}</span>
<div onClick={() => onHideModal()}>
<span>close</span>
</div>
</div>
{children} // 모달 contents
</div>
</div>
'React > Example' 카테고리의 다른 글
React - Input 자동완성(Auto Completing) 기능 만들기 (0) | 2023.04.16 |
---|---|
React - Input 값을 Tag로 만들기 (0) | 2023.04.16 |