Kakao Map 지도 상에서 마우스 오른쪽 버튼을 클릭하면 내 위치를 설정할 건지 묻는 오버레이를 띄우는 것이 목적이었다. 그래서 이벤트 핸들러를 등록하고 콜백 함수 등을 만들고 있었다. 다음은 원하는 기능을 구현하기까지의 삽질 과정.
#1 두번째 클릭부터 이벤트 핸들러가 작동하지 않음(...)
첫 오른쪽 클릭 때는 아무 문제없이 오버레이를 띄우고 새로운 좌표로 내 위치를 설정할 수 있었다.
그런데 두번째 클릭부터는 아무런 반응이 없다. 로그를 찍어보니 선택한 엘리먼트가 하나가 아니라 4개인 배열이었다. 그리고 그 이후에는 8개, 12개씩 제멋대로 늘어났다. (어이없음) 아마 엘리먼트가 지정되지 않아서 오버레이가 보이지 않았던 것 같다.
처음에는 오버레이를 띄울 때 추가된 새로운 엘리먼트가 미처 다 안 지워진 줄 알았다. 그래서 API 메소드(
customOverlay.setMap(null))를 빠트리지 않았는지, useEffect 훅에서 removeEventHandler 제대로 return 했는지 다 확인했는데 아무 문제가 없어서 잠시 실의에 빠졌다.
#2 엘리먼트의 증가 패턴: 1, 4, 8 ...
그런데 오버레이가 저렇게 규칙적으로 늘어나는 게 이상해서 생각해보니 컴포넌트 렌더링 횟수대로 늘어나고 있었다.
이벤트 핸들러를 useEffect 훅으로 감싸지 않고 그냥 지도 컴포넌트 내부에 덜렁 넣었더니 렌더링할 때마다 이벤트 핸들러가 등록되고 있었던 것이었다. 특정 조건이 아니라 '항상' 오른쪽 클릭 이벤트가 발생해야한다고 생각해서 그렇게 했던 것 같다.
수정 전
const Map = () => {
if (mapObj) {
window.kakao.maps.event.addListener(
mapObj,
"rightclick",
askSetHomeHandler
);
};
...
return ...
}
Map 컴포넌트가 렌더링 될 때마다 이벤트가 등록되니 오른쪽 클릭 이후에 askSetHomeHandler 함수도 렌더링 횟수만큼 실행됐다.
이벤트 리스너는 애초에 remove 할 필요도 없었다. 엘리먼트와 이벤트 리스너 해제는 별개의 문제이고, 어차피 오버레이 엘리먼트는 customOverlay.setMap(null) 이 코드로 인해 다 사라지기 때문.
수정 후
어쨌든 혹시 몰라서 코드를 수정하면서 return에 remove 메소드를 넣어주긴 했다.
useEffect(() => {
if (mapObj) {
window.kakao.maps.event.addListener(
mapObj,
"rightclick",
askSetHomeHandler
);
return () => {
window.kakao.maps.event.removeListener(
mapObj,
"rightclick",
askSetHomeHandler
);
};
}
}, [mapObj]);
#3 결론
사실 분명 친구 도와줄 때 똑같은 문제로 해결해준 적도 있었는데 정작 나도 똑같은 실수를 하고 있었다. 그래도 일년 전이었으면 해결도 못하고 포기했을텐데 그 동안 리액트 라이프 사이클 공부하고 훅 어떻게 쓰는지 공부도 했더니 조금씩 해결에 접근할 수 있었던 것 같다. 애증의 kakao map api...
'React' 카테고리의 다른 글
forwardRef (0) | 2021.11.22 |
---|---|
Lazy-loading (0) | 2021.05.08 |
Rendered more hooks than during the previous render (0) | 2021.03.28 |
Brad Westfall, React: "mount" vs "render" (0) | 2021.02.13 |
댓글