ㅇㅇㅈ Blog

프론트엔드 수행중

0%

onClick,onMouseDown,onMouseUp

모달창을 onClick으로 닫을 시..

프로젝트를 하다가 모달창을 띄워 input에 텍스트를 입력하는 컴포넌트를 만들었다.
백그라운드를 클릭하면 모달창이 닫히게 했는데
input의 입력값을 다시 쓰기 위해 드래그 하다 마우스 포인터가 모달 밖으로 이동하여 백그라운드까지 넘어가버리면 모달창이 닫혀버리는 아주 불쾌한 경험이 생겼다..

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
interface ModalProps {
setOpenModal: React.Dispatch<React.SetStateAction<boolean>>
}
const Modal = ({ setOpenModal }: ModalProps) => {
const handleCloseModal = (e: MouseEvent<HTMLDivElement>) => {
const target = e.target as HTMLDivElement
if (target.id === 'modal-bg') {
setOpenModal(false)
}
}
return (
<div
id="modal-bg"
style={{
backgroundColor: 'rgba(75, 75, 75, 0.773)',
width: '100vw',
height: '100vh',
position: 'absolute',
top: 0,
left: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
onClick={handleCloseModal}
>
<div
style={{
backgroundColor: '#fff',
width: '20%',
height: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<input type="text" />
</div>
</div>
)
}
export default function Home() {
const [openModal, setOpenModal] = useState(false)

const handleOpenModal = () => {
setOpenModal(true)
}
return (
<>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main style={{ position: 'relative' }}>
<div>
<button onClick={handleOpenModal}>open modal</button>
</div>
{openModal && <Modal setOpenModal={setOpenModal} />}
</main>
</>
)
}

그리하여 이것을 해결하고자 gpt에게 물어본 결과.. onMouseDown과 onMouseUp이었다.

modal쪽에 mouseIsDownOnModal state와 onMouseUp을 실행하는 함수를 더 생성해야 했다.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
const Modal = ({ setOpenModal }: ModalProps) => {
const [mouseIsDownOnModal, setMouseIsDownOnModal] = useState(false)
const handleMouseDown = (e: MouseEvent<HTMLDivElement>) => {
const target = e.target as HTMLDivElement
if (target.id !== 'modal-bg') {
setMouseIsDownOnModal(true)
}
}
const handleMouseUpAndModalClose = (e: MouseEvent<HTMLDivElement>) => {
const target = e.target as HTMLDivElement
if (target.id === 'modal-bg' && !mouseIsDownOnModal) {
setOpenModal(false)
}
setMouseIsDownOnModal(false)
}
return (
<div
id="modal-bg"
style={{
backgroundColor: 'rgba(75, 75, 75, 0.773)',
width: '100vw',
height: '100vh',
position: 'absolute',
top: 0,
left: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
onMouseDown={handleMouseDown}
onMouseUp={handleMouseUpAndModalClose}
>
<div
style={{
backgroundColor: '#fff',
width: '20%',
height: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<input type="text" />
</div>
</div>
)
}

handleMouseUpAndModalClose에서 mouseIsDownOnModalstate가 false일시 if문이 통과 되면서 modal이 닫히게 된다.
왜 false일때 닫히게 되는걸까 궁금해서
콘솔을 찍어 보았다.

첫 클릭은 모달창을 클릭, 두 번째 클릭은 bg를 클릭

mousedown일때 bg이외의 영역을 클릭시 mouseIsDownOnModal을 true로 만들어
mouseUp일때 if문을 통과 시키지 못하게 한다.
반대로 bg를 클릭할때는 mouseIsDownOnModal가 false이므로 if문을 통과해 모달을 닫는다..