프로그래밍 공부하기

DOM에서 사라진 요소는 dragEnd 이벤트가 발생할 수 없다. 본문

ErrorLog

DOM에서 사라진 요소는 dragEnd 이벤트가 발생할 수 없다.

ihl 2022. 3. 13. 18:41

  오늘은 dragEnd 이벤트가 발생하지 않는 오류를 기록해보려한다. DND(Drag & Drop)란, 위와 같이 마우스 포인터를 누른 채로 움직였다가 손을 떼는 동작을 의미한다. 일반적으로 화면상의 요소를 쉽게 움직이기 위해 사용한다.

 

  DND 이벤트는 dragstart, dragend, dragover, dragenter, dragleave, dragexit, drop 7가지가 있다. 그 중 나는 dragstart, dragend 이벤트를 사용하는 예제를 만들어 보았다.

 

See the Pen draggable by ImHyeLim1209 (@imhyelim1209) on CodePen.

 

  dragstart 이벤트가 발생하면 'dragging', dragend 이벤트가 발생하면 'nothing' 이라는 텍스트를 보여주도록 만든 간단한 예제이다. 이 때 만약, dragstart가 발생할 때 이벤트가 발생한 요소가 돔에서 사라지면 어떻게 될까?

 

See the Pen draggable false by ImHyeLim1209 (@imhyelim1209) on CodePen.

  위 코드에서 드래그를 시작하면 다시는 'nothing' 이라는 글자로 돌아오지 않는다. 그 이유는 당연히 dragend 이벤트가 발생하지 않기 때문이다. 왜 그럴까? 유저의 입장에서는 마우스를 눌렀다가 뗐으므로 dragend가 발생해야한다. 이벤트가 등록된 요소도  document이기 때문에 어디선가 dragend가 발생했다면 'nothing' 글자를 볼 수 있어야 정상이다.

 

  그 이유는 어쩌면 당연하게도, dragend 이벤트는 직전에 dragstart 이벤트가 발생한 요소에서 발생하기 때문이다. 그런데, DOM에 해당 요소가 없어져서 이벤트 버블링이 끊긴 것이다. 따라서 document에 dragend 이벤트가 도달하지 못하므로 텍스트가 변경되지 않는다.

 

  예를 들어, 리액트 에서 사용자가 드래깅하는 도중 상태가 변경되어 드래깅 중인 원본 요소가 사라지는 등의 상황에선 나와 같은 당황스러움을 느낄 수 있을 것이다. 특히 React는 document 혹은 React Root Node에 이벤트를 바인딩하여 리액트 이벤트를 발생시키는데, 이와 같은 상황이 발생하면 React에서는 아예 이벤트 자체가 발생하지 않을 것이다(네이티브 dragend 이벤트는 발생하나, 리액트 dragend이벤트는 발생하지 않아, onDragEnd 와 같은 연결이 불가능하다). 이를 어떻게 처리해주어야 할까?

See the Pen draggable improve by ImHyeLim1209 (@imhyelim1209) on CodePen.

  내가 찾은 방법은 dragstart 이벤트 처리 함수에서, 드래그 이벤트의 타겟에 dragend 이벤트와 처리함수를 별도로 연결해주는 것이다. dragend 이벤트의 버블링이 끊긴 것이지, 해당 요소에서 dragend 이벤트가 발생하지 않는다는 의미가 이니기 때문에, 해당 요소의 dragend 이벤트는 수신 가능하기 때문이다!

 

  리액트에서도 위 코드와 같이 addEventListener를 이용하여 직접 이벤트를 수신하면 사라진 요소의 dragend 이벤트를 처리할 수 있다.

 


https://stackoverflow.com/questions/24537000/react-js-events-not-firing-for-the-last-rendered-element

https://github.com/facebook/react/issues/1355

Comments