트러블슈팅이라하기엔 너무 민망한....이벤트 버블링
댕도네냥 프로젝트 마이페이지는 위와 같이 작동한다.
나의 프로필과 내가 후원한게시글, 응원한게시글, 작성한글, 내가 총 후원한 금액이 상단에 숫자로 보여진다.
그리고 해당 숫자나 글을 클릭하면 내가 그에 맞는 게시글 리스트를 띄워준다.
작성글 같은 경우 글 작성자가 후원을 종료하거나 후원을 연장할 수 있게 기획을 했기에, 기존 카드 컴포넌트와는 다른 컴포넌트를 띄워줘야 했다.(후원연장, 후원종료와 같은 버튼이 추가로 들어가야하기 때문에)
나는 이부분을 클릭시 카드가 바뀌어야하기에 useState를 통해 관리를 했다.
또한 return문이 너~무 길어져서 카드를 뿌려주는 부분을 switch case 문으로 묶어 관리를 했다.
(지금보니 코드가 너무 더럽네..)
const [likecardData, setLikeCardData] = useState([]);
const [supportcardData, setSupportCardData] = useState([])
const [writeCardData, setWriteCardData] = useState([]);
const [isWriteList, setIsWriteList] = useRecoilState(isWriteCard);
const switchCardcomponent = (isWriteList):React.ReactElement<any, string | React.JSXElementConstructor<any>> => {
switch (isWriteList) {
case "write" :
return <>
<h4 className={styles.cardWnotice}>{writeCardData?.length === 0 ? "작성하신 글이 없습니다.": name+"님의 작성글 목록입니다. "}</h4>
{writeCardData.map((card)=>
( <WriteCard card={card} key={card.id}/>)
)}
</>
case "like" :
return <>
<h4 className={styles.cardnotice}>{likecardData?.length === 0 ? "아직 응원하지 않으셨습니다.": name+"님의 응원목록입니다."}</h4>
<div className={styles.carddiv}>
{likecardData.map((list)=>
( <Mycard list={list} key={list.postId}/>)
)}
</div>
</>
case "support" :
return <>
<h4 className={styles.cardnotice}>{supportcardData.length === 0 ? "아직 후원을 하지 않으셨습니다.": "000님의 후원목록입니다."}</h4>
{supportcardData.map((list)=>
<div className={styles.carddiv}>
<Mycard list={list} key={list.postId}/>
</div>
)}
</>
default:""
}
}
버튼을 누를때마다 recoilState가 바뀌어야한다.
단순하게 음 ~ 저 숫자를 누를때마다 setState를 해주면 되겠군 ! 생각했다...
그래서 진짜 생각을 거의 안하고 손이 가는대로 아래와 같은 코드가 완성이 되었는데 ㅠㅠ
<div className={styles.myDataBox} onClick={setIsWriteList("support")}>
<div className={styles.pricebox}>
<p className={styles.price}>{data?.data.supportCnt}</p>
<span className={styles.ment}>후원한</span>
</div>
<div className={styles.pricebox} onClick={setIsWriteList("like"); }>
<p className={styles.price}>{data?.data.likeCnt}</p>
<span className={styles.ment}>응원한</span>
</div>
"응원한"("like") 버튼을 눌렀지만 recoilState는 "support"가 되어있는것..
앗 아니 이건 혹시,,,? 하고 아래에 있는 모든 버튼을 눌렀을대 State는 "support"가 되는 것이었다....!!
onClick이벤트시 state가 모두 동일하게 최상단에있는 "support"로 변하는 것을 보고 혼자서 진짜진짜 나 자신이 많이 부끄러웠다..
자바스크립트 기본서며, 기술면접을 준비할때 그렇게 외우다 싶이한 이벤트 버블링...
이벤트 버블링은 아직 나의 피부가 되지 못한것...
부끄러움을 무릎쓰고 자바스크립트의 이벤트버블링과 캡처링을 나의 피부로 만들고자 글을 작성하게 되었다.
결론부터 기술하자면 나는 해당 코드를 아래와 같이 수정했다.
<div className={styles.myDataBox} onClick={(e)=>{e.stopPropagation(); setIsWriteList("support")}}>
<div className={styles.pricebox}>
<p className={styles.price}>{data?.data.supportCnt}</p>
<span className={styles.ment}>후원한</span>
</div>
<div className={styles.pricebox} onClick={(e)=>{e.stopPropagation(); setIsWriteList("like"); }}>
<p className={styles.price}>{data?.data.likeCnt}</p>
<span className={styles.ment}>응원한</span>
</div>
이벤트 버블링
이벤트 버블링이란 HTMl 하위요소에서 상위요소로 해당 이벤트가 전달되는 것을 말한다.(상위요소에서 하위요소로는 캡처링 !)
웹 페이지 내의 버튼을 클릭했을 때 웹 페이지 내부에서 버튼을 감싸고 있는 부모 태그들 또한 클릭이벤트에 반응하는 것을 예시로 들수 있다.
이러한 이벤트 버블링은 하위요소 각각에 이벤트를 붙이지 않고 상위요소에서 하위요소의 이벤트를 제어하는 방식으로 활용이 가능하다. 이것을 이벤트 위임이라고 한다.
이벤트 버블링을 막고자 할 때가 있는데(내가 기술한 위와 같은 상황...) 다음을 활용할 수 있다.
1. stopPropagation() →부모에게 이벤트 전파 되는 것을 막음
2. stoplmmediatePropagation() → 현재 이벤트가 상위 뿐만 아니라 현재 레벨에 걸린 다른 이벤트도 동작하지 않도록 중단
3. preventDefault() → 현재 이벤트의 기본 동작을 중단
4. return false → stopPrpagation()과 preventDefault() 모두 수행한 것과 같음(query 사용시)/ preventDefault()와 같음
꼭 잊지않기...! 한번은 실수 두번은 실력...!