[TIS] react event의 stopPropagation이 예상한 대로 작동하지 않는다. (React 이벤트 위임, 캡처링과 버블링)
1.문제점

테이블 내에서 날짜를 드래그해서 선택되는것은 테이블전체(Container
)에
mousedown
이벤트가 사용되어 작동한다.
mousedown
핸들러의 경우 ref를 활용해 실제 dom에 등록하였다.즉 이는 날짜를 입력할 수 없는날에도 mousedown
이 작동되어 시간이 입력되었다.

이벤트 버블링
을 활용하면 문제를 해결할 수 있을것 같아 다음과 같은 계획을 세웠다.
(1) NotAvailableDate
컴포넌트에서 mousedown
이벤트를 포착해서
(2) 이벤트 버블링
으로 인해 전파되는 이벤트를 stopPropation()
을 활용해 막고
(3) 이로인해 Container
에 mousedown
이벤트가 전파되지않는 방식으로 문제를 막는다.
그래서 다음과 같이 코드를 작성하였다.
<NotAvailableDate
onMouseDown={(e) => {
e.stopPropagation();
}}
/>
위 방법은 예상했던 것과 달리 위 방법은 작동하지 않았다.
무엇이 문제였을까?
2.원인

위 이미지에서 보시는 것 처럼
React는 이벤트가 등록된 컴포넌트 대신 실제로는 root에서 해당 이벤트를 위임받고 처리를 한다.
지금 처한 상황을 위처럼 그려보자.

NotAvailableDate
의 onMouseDown
을 등록했을때 실제로는 위에 보는것 처럼 해당 이벤트가 위임되어 root에서 관리한다.
즉 이벤트 버블링
을 활용하여 해결하려고 했던 내 방법은 잘못된 방법이었다.

3.해결 방안
이벤트 캡처링
을 활용하면 해결할 수 있다.부모 요소를 가지고 있는 요소에서 등록되어 있는 이벤트가 작동할때
브라우저는 아래 그림과 같이 2개의 방향으로 이벤트가 전파된다.

capture phase
의 경우 최상단 html부터 시작해 해당 이벤트가 발동한곳까지 이동을 하며 발동한다.
bubble phase
의 경우 해당 이벤트가 발동한곳부터 시작해 html까지 이동하며 발동한다.
즉 해당 root
에서 mousedown
이벤트
를 받아 capture phase
에서 전파를 시키지 않으면 된다.

이를 코드로 작성하면 NotAvailableDate에
기존에 작성했던 onMouseDown
대신 onMouseDownCapture
로 작성하면 된다.
<NotAvailableDate
onMouseDownCapture={(e) => {
e.stopPropagation();
}}
/>
다음과 같이 문제가 해결된 것을 볼 수 있다.

4.이를 통해 배운점
이번에 문제를 해결하면서 React의 컴포넌트에 등록된 이벤트는 root에서 관리하는 것을 알게 되었다.
추가적으로 이벤트 캡처링과 버블링에 대해 다시 한번 집고 넘어갈 수 있어서 좋은 공부가 됬다.
마지막으로 이 글을 통해 react에 등록한 event가 실제 돔에 등록한 이벤트 사이에 문제를 겪는 분들께
도움이 되었으면 좋겠다.
해당 코드는 아래 커밋 기록에서 더 자세하게 확인할 수 있습니다. 감사합니다.
references
https://ko.javascript.info/bubbling-and-capturing
https://reactjs.org/blog/2020/10/20/react-v17.html#changes-to-event-delegation
https://developer.mozilla.org/ko/docs/Learn/JavaScript/Building_blocks/Events
Uploaded by N2T