오늘은 event.composedPath()에 대해 적어보려 한다.
먼저 mdn 공식 문서를 인용해보자면,
The composedPath() method of the Event interface returns the event’s path which is an array of the objects on which listeners will be invoked. This does not include nodes in shadow trees if the shadow root was created with its ShadowRoot.mode closed.
대략적으로 이런 신기한 메소드이다! 👏🏻
요약하자면, 이벤트가 발생하는 노드에서부터 이벤트가 거쳐가는 모든 path를 배열로 반환한다.
그렇다면 이걸 어디에 썼느냐..!
이런 자그마한 기능에 쓰였다...
네비바에 검색 기능을 달아놓고 검색 결과를 보여주는 모달창을 달았다.
이 결과창에는 인기 검색어나, 최근 검색 결과를 저장해놓는다.
그리고 저 모두 삭제를 클릭하면 전부 다 지워지면서 모달창은 그대로 남아있어야 한다.
다만 문제는 서치 input에 onblur 이벤트로 모달창이 꺼지도록 구현해야 하는데, 그러면 저 모두 삭제를 클릭하면 input의 onBlur 이벤트가 우선적으로 적용되어 모달창이 계속 꺼지기만 했던 것..!
따라서 이 event.composedPath() 메소드를 유용하게 써먹었다.
먼저 <Search inputRef={this.input} />
search라는 컴포넌트 자체에 ref를 달아주었다.
그리고 다음과 같이 handleBlur라는 함수를 만들었다.
(당시에는 class component를 쓰던 시기였으므로..) componentDidMount와 componentWillUnmount를 사용해 window 전역적으로 해당 이벤트 리스너를 추가하고 삭제해주었다.
componentWillUnmount를 해주면서 componentDidMount에서 직접 생성한 DOM을 제거할 수 있다..!
이렇게 되면 handleInputBlur에 console.log 찍어본 부분이 어떻게 나오냐하면,
composedPath()를 찍어 놓은 부분을 보면 해당 이벤트가 어떤 노드를 지나가는지 배열로 리턴한다. 따라서 이 composedPath에 속하는 것들을 클릭하지 않았을 때만 (isExist가 false일 때만) List가 active되지 않도록 setState하도록 함수를 만들 수 있었다.
사실 처음에는 React DOM으로 ref를 사용해서 해결하려고 시도했으나, 좋은 방법을 찾지 못했고 해당 방법으로 해결했다.
후에 functional component로 리팩토링 한다면 ref를 사용해 해결해보겠다.
ps.composedPath() method의 존재를 알려준 종택 멘토님께 이 TIL을 바칩니다..