input이 포커스되었을 때만 보여지는 컴포넌트가 있었고 그 중 일부분을 클릭할 때 동작을 처리하도록 onClick 속성에 함수를 넣어주었습니다.
{isFocusing && (
<HistoryBox className={`${isMounted ? 'opened' : ''}`}>
<List>
{history.map((hist) => (
<Item
key={uuid()}
onClick={() => {
handleClick(hist)
}}
>
<History>{hist}</History>
</Item>
))}
</List>
</HistoryBox>
)}
이런 식으로 조건부 렌더링되는 부분에 onClick을 적용하였는데 이벤트가 발생되지 않았습니다.
원인은 정말 간단하였습니다.
이럴 때는 onMouseDown
에서 preventDefault
를 적용해주면 blur 이벤트를 방지하고 click 이벤트를 적용시킬 수 있습니다.
onClick
자체를 onMouseDown
로 바꿔도 blur 전에 동작은 하겠지만 소프트웨어의 예측 가능성을 손상시킬 수 있기 때문에 좋지 않습니다.
onMouseDown
이벤트와onClick
이벤트는 엄연히 다른 이벤트입니다.
onClick
를 onMouseDown
으로 바꾼 경우에는 사용자가 소프트웨어에서 클릭이 아니라 마우스를 누른 그 시점에 바로 이벤트가 발생할 것이라고 예측할 수 있는 상황이어야 합니다.onClick
이벤트에서 핸들링하는 것이 맞습니다.우리가 해야하는 것은
onClick
이벤트를 다른 이벤트로 바꾸는 것이 아니라onClick
이벤트가 발생될 수 있도록onBlur
이벤트를 막아주어야 하는 것입니다.
onMouseDown
이벤트는 default로 blur 이벤트를 발생시키는 데 preventDefault
를 해주면 onClick
이벤트가 동작할 수 있도록 blur 이벤트를 막아줍니다.
결과적으로 수정한 코드는 다음과 같습니다.
{isFocusing && (
<HistoryBox className={`${isMounted ? 'opened' : ''}`}>
<List>
{history.map((hist) => (
<Item
key={uuid()}
onMouseDown={(e) => {
e.preventDefault()
}}
onClick={() => handleClick(hist)}
>
<History>{hist}</History>
</Item>
))}
</List>
</HistoryBox>
)}
처음에는 그냥 onClick
을 onMouseDown
으로 바꾸니깐 잘 작동하여서 문제가 없는 줄 알았습니다.
하지만, 엄밀히 말하면 onMouseDown
은 마우스를 누른 즉시 발생되고 onClick
은 마우스를 눌렀다가 뗄 때 비로소 발생됩니다.
이번 에러 핸들링은 소프트웨어의 예측 가능성을 항상 염두에 두고 이벤트를 핸들링해야 하는 것의 중요성을 알 수 있었던 좋은 경험이었습니다.
좋은글 감사합니다 !! 궁금한점이 클릭 전에 블러 이벤트가 발생한다고 하셨는데요 블러 이벤트가 발생하는것은 어떻게 아셨나요 !?