rect modal의 바깥 창을 눌렀을 때 닫히게 하는 방법이다. wrapper 를 사용하는 방법이 있고 ref 를 사용하는 방법이 있는데 ref를 사용했다.
import { useState, useRef, useEffect } from "react"; const MyComponent = () => { const [actionModal, setActionModal] = useState(false); const node = useRef(); useEffect(() => { const clickOutside = (e) => { // 모달이 열려 있고 모달의 바깥쪽을 눌렀을 때 창 닫기 if (actionModal && node.current && !node.current.contains(e.target)) { setActionModal(false); } }; document.addEventListener("mousedown", clickOutside); return () => { // Cleanup the event listener document.removeEventListener("mousedown", clickOutside); }; }, [actionModal]); return (<div ref={node}> <div className="flex shrink-0 pointer" onClick={() => setActionModal((pre) => !pre)} > <img src="/images/more_horiz_black_24dp.svg" /> </div> {actionModal ? ( <div style={{ position: "fixed", backgroundColor: "white", padding: "0.625rem", border: "1px solid grey", zIndex: 10, borderRadius: "4px", }} > <div className="p-10">action sheet</div> <div className="p-10">action sheet</div> <div className="p-10">action sheet</div> </div> ) : null} </div>) } export default MyModal;
기능 위주로 정리된 글
<button>열기</button> <ModalBg> <Modal> 모달 내용 <button>취소</button> </Modal> </ModalBg>
state
모달이 열린 상태일 때는 modal state를 true로 하고 꺼진 상태일 때는 false로 할 거다.
modal state
true
false
const [modal, setModal] = useState(false);
<button onClick={ () => setModal(true) }>모달 열기</button>
setModal
{ modal === true ? <ModalBg> <Modal> <p>모달창입니다.</p> <button>취소</button> </Modal> </ModalBg> : null }
null
{ modal && <ModalBg> <Modal> <p>모달창입니다.</p> <button>취소</button> </Modal> </ModalBg> }
<ModalBg>생략/ModalBg>
{ modal == true ? <ModalBg> <Modal> <p>모달창입니다.</p> <button onClick={ () => setModal(false) }>취소</button> </Modal> </ModalBg> : null }
useRef를 이용해서 모달 백그라운드를 제어해줘야 한다.
useRef
const outside = useRef();
ref
<ModalBg ref={oustside} >
outside.current // => ModalBg
<ModalBg ref={oustside} onClick={ (e) => { if(e.target == outside.current) setModal(false) } } >
oustside.current
import { useState, useRef } from "react"; const Page = () => { const [modal, setModal] = useState(false); const outside = useRef(); return ( <> <button onClick={ () => setModal(true) }>모달 열기</button> { modal && <ModalBg ref={outside} onClick={ (e) => { if(e.target == outside.current) setModal(false) } } > <Modal> 모달 내용 <button onClick={ () => setModal(false) }>취소</button> </Modal> </ModalBg> } </> ) } export default Page;