일반적으로 모달 닫기 버튼 외에 모달 영역 밖을 클릭 시 닫을 수 있어야 된다.
모달 열고 닫기 기본형
useState를 활용해 클릭하는 버튼을 이전 값에 반대되는 값이 들어오게 해서 true면 모달 창이 보이고 false면 닫히게 만들었다.
export default function Modal() {
const [modal, setModal] = useState(false);
return (
<div>
<div onClick={() => setModal((prev) => !prev)}>
버튼
</div>
{modal && (
<div>
모달
</div>
)}
</div>
);
}
모달 영역 외 클릭시 모달 닫기
- useRef를 사용하여 modalBtnRef와 modalRef를 생성하여 modalBtnRef**(모달을 열고 닫는 버튼),** modalRef**(실제 모달)**을 참조합니다.
- useEffect를 활용하여 modal 상태 변경을 감지합니다.
- clickOutsideClose 함수를 활용하여 참조한 DOM 요소가 이벤트의 대상인 e.target포함되어있는지 여부를 확인합니다. 그래서 modalBtnRef, modalRef DOM 요소가 포함되어있지 않으면(false 값이 나와야되서 !를 붙임) setModal(false)로 바꾸어 모달 창을 닫게 한다.
- document.addEventListener() : 문서 전체에 대한 클릭 이벤트를 수신하고, 모달 외부를 클릭하면 모달을 닫도록 합니다.
- document.removeEventListener() : 클릭 이벤트 리스너를 제거하는 정리 함수가 포함되어 메모리 누수를 방지합니다.
export default function Modal() {
const [modal, setModal] = useState(false);
const modalBtnRef = useRef<HTMLDivElement | null>(null);
const modalRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
const clickOutsideClose = (e: { target: any }) => {
if (
modal&&
!modalBtnRef.current?.contains(e.target) &&
!modalRef.current?.contains(e.target)
)
setModal(false);
};
document.addEventListener("click", clickOutsideClose);
return () => document.removeEventListener("click", clickOutsideClose);
}, [modal]);
return (
<div>
<div ref={modalBtnRef} onClick={() => setModal((prev) => !prev)}>
버튼
</div>
{modal && (
<div ref={modalRef}>
모달
</div>
)}
</div>
);
}
modalBtnRef.current?.contains(e.target) 설명
modalBtnRef.current는 useRef를 사용하여 참조한 DOM 요소를 가리킨다.
cotains메서드는 DOM 요소의 메서드로, 괄호 안의 인자로 전달된 요소를 현재 요소가 포함하고 있는지 여부를 불리언으로 반환한다.
e.target은 클릭 이벤트에서 발생한 이벤트 객체의 속성으로, 이벤트가 발생한 요소를 나타낸다.
⇒ modalBtnRef.current?.contains(e.target)은 모달 버튼이 클릭 이벤트의 대상인 e.target을 포함하고 있는지 여부를 확인합니다.
modalRef**(실제 모달)** console.log
메모리 누수를 방지 설명
메모리 누수(Memory Leak)란 프로그램이 더 이상 필요하지 않은 메모리를 해제하지 않고 유지하는 상태를 의미합니다. 메모리 누수가 발생하면 시스템의 메모리가 늘어나고, 결국 시스템이 느려지거나 불안정해질 수 있습니다. JavaScript 및 React 애플리케이션에서도 메모리 누수가 발생할 수 있습니다.
useEffect 훅에서 클릭 이벤트 리스너를 등록하고 있다면, 해당 이벤트 리스너를 명시적으로 제거하지 않을 경우, 컴포넌트가 소멸되더라도 해당 이벤트 리스너는 계속 남아있게 됩니다. 이는 메모리 누수를 일으킬 수 있습니다. 이를 방지하기 위해 클린업(cleanup) 함수를 사용하여 등록한 이벤트 리스너를 제거합니다.
예시 코드
useEffect(() => {
const handleClick = () => {
console.log('Button clicked!');
};
document.addEventListener('click', handleClick);
// 클린업 함수: 컴포넌트가 언마운트될 때 실행됨
return () => {
document.removeEventListener('click', handleClick);
};
}, []);
위의 코드에서 return 블록 안에 작성된 함수는 컴포넌트가 언마운트될 때 실행된다. 이 함수에서는 클릭 이벤트 리스너를 제거하고, 이를 통해 메모리 누수를 방지합니다. 클린업 함수를 이용해 필요하지 않은 자원을 해제함으로써 애플리케이션의 성능과 안정성을 향상시킬 수 있다.
참고
'React' 카테고리의 다른 글
ExcelJS 다운로드 & 엑셀 파일 업로드 (0) | 2024.08.24 |
---|---|
apexcharts (0) | 2024.08.24 |
React에서 Lottie 사용하기 (0) | 2024.08.24 |
React Datepicker (0) | 2024.08.23 |
상단 이동 버튼 & 스크롤 시 버튼 나타나기 (0) | 2024.08.23 |