Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- 쌓임맥락
- nextjs사용법
- SCSS extend
- Vue
- git 같은계정 다른 컴퓨터
- 프로그래머스 프론트엔드 데브코스
- KDT 프로그래머스
- 다른컴퓨터에서 git사용
- 폼 입력 바인딩
- SCSS use
- 이벤트 수식어
- flex
- vue 이벤트 수신
- 프로그래머스 데브코스 프론트엔드
- 고양이 사진 검색기
- vue 지역 컴포넌트
- react next
- Spacer
- vue mixin
- 프로그래머스 K_Digital Training
- SCSS forward
- intersection opserver
- 프로그래머스 데브코스
- vuex map
- KDT 프로그래머스 데브코스 프론트엔드
- postcss
- netlify redirect
- SCSS import
- 리액트
- 리스트 렌더링
Archives
- Today
- Total
혼자 적어보는 노트
[React] 영역 밖 클릭시 이벤트 / 모달 닫기 본문
영역 밖 클릭 시 이벤트 발생되는 것들을 몇차례 했었는데
이번에는 모달 컴포넌트의 바깥 영역을 클릭할 경우 해당 모달이 닫히는 것을 구현해보려한다.
const modalRef = useRef();
const [profileModal, setProfileModal] = useState(false);
const handleCloseModal = (e) => {
if (profileModal && !modalRef.current.contains(e.target)) {
setProfileModal(false);
}
};
useEffect(() => {
window.addEventListener("click", handleCloseModal);
return () => {
window.removeEventListener("click", handleCloseModal);
};
}, [profileModal]);
return{
<>
{profileModal && (
<div ref={modalRef}>
<ProfileModal displayName={displayName} profileImg={profileImg} />
</div>
)}
</>
}
발생한 문제사항들
1. ref로 함수형 컴포넌트 자체를 선택할 수 없다. (class컴포넌트는 가능)
해결방안 : div로 감싸서 해당 div에 ref를 걸어준다.
2. useEffect의 실행을 컴포넌트 생성 시 1번만 하게 된다면
profileModal가 true로 변경됨에도 불구하고
handleCloseModal에서 profileModal을 계속 false로 읽게된다.
해결 방안 : profileMadal의 상태가 변경할 때 마다 useEffect를 실행해 주게 변경하면 된다.
해결 방안2 : state를 관리하는 부모 컴포넌트에 useEffect를 하지 않고 모달컴포넌트에 해당 useEffect를 넣어준다.
이렇게 하면 modal컴포넌트가 활성화 되어 있을 경우에만 이벤트를 작동시킬 수 있다.
3. 모달을 관리하는 코드 외에 다른 코드들이 추가되어 있을 경우 코드가 복잡해보이며,
이 후 다른 곳에서도 모달을 사용할 예정인데 재사용성이 조금 떨어져보인다.
해결 방안 : 모달의 state를 관리하는 hooks를 만들어서 관리한다.
최종 수정
Header.js (부모 컴포넌트)
import ProfileModal from "./ProfileModal";
import { useModal } from "../../lib/custom/useModal";
const Header = (props) => {
const { modalState, handleShowModal, handleCloseModal, modalRef } =
useModal();
const onClickProfile = () => {
handleShowModal();
};
return (
<header>
<div className="profile">
<div onClick={onClickProfile}>
<img src={profileImg} alt="profile" />
</div>
</div>
{modalState && (
<div ref={modalRef}>
<ProfileModal
handleCloseModal={handleCloseModal}
/>
</div>
)}
</header>
);
};
export default Header;
ProfileModal.js (modal 컴포넌트)
const ProfileModal = ({ handleCloseModal }) => {
useEffect(() => {
window.addEventListener("mousedown", handleCloseModal);
return () => {
window.removeEventListener("mousedown", handleCloseModal);
};
}, []);
return (
<div className="profile-modal">
<div className="profile-wrapper">
</div>
</div>
);
};
export default ProfileModal;
useModal.js
import { useRef, useState } from "react";
export const useModal = () => {
const [modalState, setModalState] = useState(false);
const modalRef = useRef();
const handleShowModal = () => {
setModalState(!modalState);
};
const handleCloseModal = (e) => {
if (modalState && !modalRef.current?.contains(e.target)) {
setModalState(false);
}
};
return {
modalState,
handleShowModal,
handleCloseModal,
modalRef,
};
};
'React' 카테고리의 다른 글
[React] styled-component (0) | 2022.03.06 |
---|---|
[React] input type="file" 커스터마이징 하기 (0) | 2022.03.03 |
[React] 활성화된 input focus 해제 / blur() (0) | 2022.01.17 |
[React] useCallback에 대한 이해 / 함수 재사용 (0) | 2022.01.17 |
[React] 리렌더링 조건 / React memo (0) | 2022.01.14 |
Comments