위의 버튼을 클릭 시, 모달창을 보이기 위해서 모달창을 키고 끄는 상태를 관리하는 state를 생성했다.
그리고 Modal 컴포넌트에게 해당 state를 전달하여 state값에 따라 렌더링의 변화를 주게끔하였고 모달창을 닫을 수 있는 함수를 전달하는 방식으로 구현하였다.
function DetailImageModalCotainer() {
const [modalState, setModalState] = useState(false);
function onClose() {
setModalState(false);
}
function onOpen() {
setModalState(true);
}
return (
<>
<AllImgBtn onOpen={onOpen} />
<Modal modalState={modalState} onClose={onClose} width={'70vw'} height={'80vh'}>
<div>JSX 태그 안</div>
<div>children prop</div>
</Modal>
</>
);
}
<Modal> JSX 태그 안
에 있는 것들은 Modal 컴포넌트의 children prop으로 전달되어 아래와 같은 방식으로 Modal 컴포넌트에서 전달받아 출력할 수 있다.
function Modal({ modalState, onClose, children, width, height }) {
if (!modalState) return null;
return (
<div css={modalBackground}>
<div css={modalContainer({ width, height })}>
<a onClick={onClose} css={closeBtn}>
❮
</a>
{children}
</div>
</div>
);
}
모달 창의 바깥 범위를 클릭 했을 때 modalState 값에 따라 모달창을 닫아주기 위해 eventlistener를 사용하며 알게 된 사실이다.
const [modalState, setModalState] = useState(false);
function handleClick(e) {
console.log(modalState);
}
useEffect(() => {
window.addEventListener('click', handleClick);
return () => {
window.removeEventListener('click', handleClick);
};
}, []);
위의 방식대로 하게 되면 modalState값이 어떤 동작에 의해 true로 변경되었을 때 클릭 이벤트시 호출되는 handleClick함수에서 로그로 찍히는 값은 항상 false
이다.
이는 JS에서의 클로저 때문
이다.
이를 수정하기 위해서는 아래 코드와 같이 modalState값이 업데이트 되었을 때마다 핸들러를 새롭게 등록시켜줘야 원하는 state 값을 얻을 수 있다.
const [modalState, setModalState] = useState(false);
function handleClick(e) {
console.log(modalState);
}
useEffect(() => {
window.addEventListener('click', handleClick);
return () => {
window.removeEventListener('click', handleClick);
};
}, [modalState]);