FE (Front End) (구)/React

React (리액트) onKeyDown 이벤트 두 번 실행 되는 이슈, 한 번만 실행하기

B_Tae 2022. 7. 1. 23:34

onKeyDown이 2번 실행되는 이슈

프로젝트를 하면서 검색 기능을 작성하던 중 생긴 이슈가 있다.
검색창 하단에 나타내는 목록을 방향키로 조회를 하는데, 처음에 2번 실행돼 첫 번째 항목이 아닌 두 번째 항복으로 바로 갔다.

우선 이렇게 2번 입력되는 원인은 한글은 조합하여 사용하기 때문이라고 생각하고 있다. 영문이나 숫자는 위와같은 이슈가 발생하지 않을 것이다. (공식 문서에서 확인을 못해봤다)
컴퓨터는 작성된 한글이 완성된 단어인지, 작성 중인지 구분할 수 없다 그렇기 때문에 방향키를 누르면, 단어를 완성하면서 실행되고 그 이후에 한 번 더 실행하게 된다. (추측)


이를 해결할 수 있는 방법을 찾다 2가지를 찾게 됐는데, 경우에 따라서는 1가지일 것이다. (제가 이 1가지만 가능했습니다 )

  1. 우선 onKeyDown 대신 onKeyPress를 사용하는 것이다. onKeyPress는 조합문자를 판단하지 않기 때문에 두 번 실행되는 이슈는 없을 것이다. 다만 shift, 방향키 backspace 등등 인식하지 않는 키가 많다. 한글도 인식하지 않는다.
    이걸로 해결하는 경우도 있지만 거의 없을 것 같다. 나 또한 한글로 검색을 하기 때문에 다른 방법을 선택했다.

  1. KeyboardEvent.isComposing 사용하기
    KeyboardEvent.isComposing는 입력한 문자가 조합문자인지 아닌지를 판단한다. 즉 한글이라면 true, 영문이나 숫자 등 조합문자가 아니라면 false를 반환한다.
    한글로 작성 후 방향키 이벤트를 일으켜보면 true가 반환된 다음 false가 반환되는 것을 확인 할 수 있었다. 그래서 나는 !e.nativeEvent.isComposing를 조건에 추가하여 false일 경우에만 명령을 실행하도록 하여, 2번 실행을 한 번으로 줄였다 .

KeyboardEvent.isComposing ( MDN )


작성한 예시 코드 일부

if (
stockArr.length !== 0 &&
selectStockState &&
// 조합 문자가 아닐 경우에만 실행
!e.nativeEvent.isComposing
) {
if (e.code === "ArrowDown" && Number(stockIndex) !== stockArr.length) {
setStockIndex(stockIndex + 1);
// 자동 스크롤 내리기
// 4번째마다 스크롤
if (stockIndex % 4 === 0 && stockIndex !== 0) {
const  scrollPoint =
wrapTagStockList?.current?.children[stockIndex - 1];
scrollPoint.scrollIntoView({ behavior:  "smooth" });
}
}
...