사내 디자인 가이드 중 이런 형태의 가이드를 구현해야 할 일이 있었다.
입력란에 포커싱 되고 타이핑이 있을 때만 옆의 x 버튼을 보이게 하는 기능을 구현해야 했다.
처음엔 css로 visibility를 제어하고, input에 포커싱이 될때만 버튼 영역을 그리려 했다.
.flexible-delete {
visibility: hidden;
&.active {
visibility: visible;
}
}
const [isFocus, setIsFocus] = useState(false)
const onFocus = () => setIsFocus(true)
const onBlur = () => setIsFocus(false)
return (
<div onFocus={onFocus} onBlur={onBlur}>
<input type="text" {...props} />
<input type="text" {...props} />
<input type="text" {...props} />
</div>
{isFocus && (
<button
type="button"
onClick={handleClear}>
<!-- 엘리먼트 -->
</button>
)}
)
하지만 onClick 이벤트보다 Blur 이벤트가 먼저 trigger되는 바람에 입력 내용을 삭제하는 클릭 이벤트가 trigger되기도 전에 버튼이 사라지는 이슈가 있었다.
이럴 때 onMousedown 이벤트 발생 시 blur 이벤트가 trigger되는 것을 막는다.
onMouseDown will cause a blur event by default, and will not do so when preventDefault is called. Then, onClick will have a chance to be called. A blur event will still happen, only after onClick.
onMouseDown 시 blur 이벤트를 막으면 onClick 이벤트가 실행될 수 있다.
const [isFocus, setIsFocus] = useState(false)
const onFocus = () => setIsFocus(true)
const onBlur = () => setIsFocus(false)
const handleMouseDown = (e) => e.preventDefault() // 이벤트 전파 막음
return (
<div onFocus={onFocus} onBlur={onBlur}>
<input type="text" {...props} />
<input type="text" {...props} />
<input type="text" {...props} />
</div>
{isFocus && (
<button
type="button"
onMouseDown={handleMouseDown}
onClick={handleClear}>
<!-- 엘리먼트 -->
</button>
)}
)
이제 원하는대로 동작할 수 있다!
Q. 왜 onClick을 onMouseDown으로 대체하지 않았나?
onMouseDown은 onClick의 대체 함수가 정확히는 아니다. 얼핏 보기에는 비슷하게 동작한다고 생각될 수 있지만 엄연히 다른 이벤트이다.
To illustrate: when accidentally clicking on a button, users expect to be able to hold down the mouse click, drag the cursor outside of the element, and release the mouse button, ultimately resulting in no action. onClick does this. onMouseDown doesn't allow the user to hold the mouse down, and instead will immediately trigger an action, without any recourse for the user. onClick is the standard by which we expect to trigger actions on a computer.
참고 링크
'Today I Learn > 이슈 해결' 카테고리의 다른 글
[React] history.block으로 뒤로가기 막기 (blocking-transition) (0) | 2021.07.08 |
---|---|
getEventListeners로 등록된 이벤트리스너 확인하기 (0) | 2021.06.14 |
react-router-dom __RouterContext 미존재 이슈 (0) | 2021.01.21 |
react-testing-library의 “not wrapped in act” Errors 원인과 해결법 (2) | 2021.01.08 |
[JS] encodeURIComponent, encodeURI 이슈 (0) | 2020.11.18 |