todo를 만들던 와중 또 하나의 문제가 발생했습니다.
stopPropagation() 메서드는 현재 이벤트가 캡처링/버블링 단계에서 더 이상 전파되지 않도록 방지합니다.
Event.stopPropagation() - Web API | MDN
Event 인터페이스의 stopPropagation() 메서드는 현재 이벤트가 캡처링/버블링 단계에서 더 이상 전파되지 않도록 방지합니다. 전파를 방지해도 이벤트의 기본 동작은 실행되므로, stopPropagation()이 링
developer.mozilla.org
분명 이전 pokemon 개인 프로젝트를 할 때는 e.stopPropagation()을 통해 이벤트 버블링의 전파를 막았는데 왜 이번에는 안될까....
현재 코드는 이렇게 구성되어 있습니다.
const handleDetail = (e, id) => {
navigate(`/about?id=${id}`);
};
const handleCheckBox = (e, id) => {
e.stopPropagation();
setTodo([...todo].map((todo) => (todo.id === id ? { ...todo, isDone: !todo.isDone, end_date : todo.isDone ? '' : new Date() } : todo)));
};
분명 생각대로라면 checkbox를 클릭하면 e.stopPropagation을 통해 상위의 이벤트는 일어나서는 안됩니다. 그런데. 왜.

2개의 이벤트가 왜 다 실행되는거니....
console을 통해 어떻게 동작하는지 알아봅시다.

??? handleDetail이 실행된 후 handleCheckBox가 실행되는 모습입니다.
왜 그런지 이해가 안되서 직전 프로젝트와 코드를 비교해보았습니다.
<StPokemonCard onClick={handelGoDetail}>
<StPokemonBtn $props={'remove'} onClick={(e) => handleRemoveBtn(e, item)}>
삭제
</StPokemonBtn>
</StPokemonCard>
<TodoItem key={todo.id} onClick={(e) => handleDetail(e, todo.id)}>
<span>{todo.title}</span>
<Checkbox
type="checkbox"
checked={todo.isDone === true}
onChange={(e) => handleCheckBox(e, todo.id)}
/>
</TodoItem>
차이라면 onClick과 onChange로 이벤트 종류가 다른 것입니다...
그러면 onClick과 onChange의 동작 순서 때문이겠죠?
위에서 봤듯이 onClick 이벤트는 클릭한 순간 실행되고 onChange 이벤트는 상태가 변경된 후에 실행됩니다.
그럼 checkbox의 이벤트를 onClick으로 변경해봅시다.

이렇게 이벤트 전파를 막을 수 있는 것을 알 수 있습니다.
하지만 <input> 요소에 checked prop을 설정했지만, 해당 입력 요소에 onChange 핸들러를 추가하지 않았기 때문에 오류가 발생합니다. 이를 위해 onClick이 아닌 onChange 핸들러를 사용하여 해결해 봅시다.
이벤트 위임을 활용하여 handleDetail 함수에 early return을 적용해 봅시다.
const handleDetail = (e, id) => {
if (e.target.tagName === 'INPUT') {
return;
}
console.log('handleDetail 실행')
navigate(`/about?id=${id}`);
};
클릭한 요소가 input 태그일 시 return을 통해 함수를 조기에 종료시킵니다.

e.stopPropagation()을 직접 사용하기보다는 이벤트 위임을 통해 early return을 활용하는 방법이 더 깔끔하고 유지보수에 유리할 수 있습니다. onClick과 onChange 이벤트의 차이를 잘 이해하고 사용해야겠습니다~