카테고리 바를 만들던 도중 발견한 오류다.
카테고리의 각 항목을 클릭하면, 클릭한 항목의 배경이 생겨 선택되었다는 것을 보여주는 CSS다.
JS구조는 아래와 같다.
categoryFilter.map((item, index) => (
<Box
key={index}
...
onClick={(e) => {
setBtnActive(e.target.textContent);
}}
className={btnActive === item.text ? "active2" : ""}
간단하다. map으로 뿌려준 각각의 item의 text값과, 내가 클릭한 항목의 text값이 같으면, 동적으로 클래스 명을 부여하는 방식이다.
하지만 위의 gif에서 보이듯이, 텍스트 부분이 아닌 색깔도형 (mui에서 div같은 태그임)나 텍스트의 살짝 옆 여백을 누르면 배경이 사라지는 오류가 발생하였다.
원인을 찾기위해 클릭 이벤트를 console.log(e.target.textContent)로 찍어보았다.
위 결과는 카테고리의 맨 왼쪽 색깔도형부터 맨오른쪽 텍스트부분까지 순차적으로 클릭해본 결과이다.
보다시피 색깔도형을 클릭할 때만 값이 출력되지 않음을 알 수 있다.
원인은 내가 에 부여한 onClick event를 자식 요소들에게까지 적용됐기 때문이다. 이를 event전파 또는 버블링 이라고 하나보다.
e.target은 부모 요소로부터 이벤트가 전파되어 실제 이벤트가 발생한 자식요소가 클릭되는 반면, e.currentTarget는 클릭이벤트를 걸어놓은 요소만을 가르킨다.
하지만, 나는 Text의 값이 필요하다. e.currentTarget의 값은 null로서, e.target처럼 부모노드로 넘어갈 수 없었다.
참고문헌 개인블로그
이는 현재 발생한 이벤트 이후의 이벤트들을 막아주는 메서드라고한다.
즉 버블링을 멈춰주는 메서드다.
하지만 이를 사용하였을 때 자식요소의 이벤트가 아예 사라져서, 자식요소 클릭 시 아무것도 클릭되지 않았다. 내가 원하는 것은 자식 요소를 클릭했을 때 부모요소의 이벤트가 뜨고, 그 이벤트의서 event.target을 통해 text값에 접근하는 것이다.
참고문헌 개인블로그
이 방법은 css단 해결방법은 아니지만, 근본전인 해결책을 줄 수 있을 듯하다. 왜냐하면, text는 눌러야만 출력 텍스트를 눌러야만 되는 반면 index는 map으로 뿌려지는 요소들 모두가 공통적으로 가지고 있는 요소이기 때문이다.
categoryFilter.map((item, index) => (
<Box
key={index}
...
onClick={(e) => {
setBtnActive(index);
}}
className={btnActive === index ? "active2" : ""}
이제 잘 된다 😂