[React] 조건부 렌더링되는 컴포넌트에서 onClick이 안될 때

Jin·2022년 4월 1일
1

에러 로그

목록 보기
4/6

input이 포커스되었을 때만 보여지는 컴포넌트가 있었고 그 중 일부분을 클릭할 때 동작을 처리하도록 onClick 속성에 함수를 넣어주었습니다.

{isFocusing && (
  <HistoryBox className={`${isMounted ? 'opened' : ''}`}>
    <List>
      {history.map((hist) => (
        <Item
          key={uuid()}
          onClick={() => {
            handleClick(hist)
          }}
        >
          <History>{hist}</History>
        </Item>
      ))}
    </List>
  </HistoryBox>
)}

이런 식으로 조건부 렌더링되는 부분에 onClick을 적용하였는데 이벤트가 발생되지 않았습니다.

원인은 정말 간단하였습니다.

click 이벤트보다 포커스가 해제되는 blur 이벤트가 먼저 발생하기 때문에 click 이벤트는 발생되기도 전에 사라져버리는 것이었습니다.

이럴 때는 onMouseDown에서 preventDefault를 적용해주면 blur 이벤트를 방지하고 click 이벤트를 적용시킬 수 있습니다.

만약, onClick 자체를 onMouseDown로 바꿔도 blur 전에 동작은 하겠지만 소프트웨어의 예측 가능성을 손상시킬 수 있기 때문에 좋지 않습니다.

onMouseDown 이벤트와 onClick 이벤트는 엄연히 다른 이벤트입니다.

onClickonMouseDown으로 바꾼 경우에는 사용자가 소프트웨어에서 클릭이 아니라 마우스를 누른 그 시점에 바로 이벤트가 발생할 것이라고 예측할 수 있는 상황이어야 합니다.

하지만, 이 상황을 포함하여 일반적으로 마우스를 눌렀다 떼는 클릭 시점에서 이벤트가 발생된다고 예측하기 때문에 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>
)}

느낀 점

처음에는 그냥 onClickonMouseDown으로 바꾸니깐 잘 작동하여서 문제가 없는 줄 알았습니다.

하지만, 엄밀히 말하면 onMouseDown은 마우스를 누른 즉시 발생되고 onClick은 마우스를 눌렀다가 뗄 때 비로소 발생됩니다.

이번 에러 핸들링은 소프트웨어의 예측 가능성을 항상 염두에 두고 이벤트를 핸들링해야 하는 것의 중요성을 알 수 있었던 좋은 경험이었습니다.

profile
배워서 공유하기

1개의 댓글

comment-user-thumbnail
2023년 3월 23일

좋은글 감사합니다 !! 궁금한점이 클릭 전에 블러 이벤트가 발생한다고 하셨는데요 블러 이벤트가 발생하는것은 어떻게 아셨나요 !?

답글 달기