Frontend/Next.js
[Next.js][ISSUE] Textarea & input 에서 한글 입력시 마지막 글자 중복 입력됨 (+Enter key)
JOKUN
2024. 7. 18. 13:28
Reason
socket을 이용해 실시간 채팅 기능 구현하던중에 아래와 같이 메시지 전송을 했는데 마지막 글자가 한번씩 더 보내지는 현상 발생
<TextareaAutosize
placeholder="Start a new message"
value={content}
onKeyDown={onEnter}
onChange={onChangeContent}
/>
const onChangeContent: ChangeEventHandler<HTMLTextAreaElement> = (e) => {
setContent(e.target.value);
};
const onEnter: KeyboardEventHandler<HTMLTextAreaElement> = (e) => {
console.log(e.key === "Enter", e);
if (e.key === "Enter") {
if (e.shiftKey) {
return;
}
e.preventDefault();
if (!content?.trim()) {
return;
}
onSubmit();
setContent("");
}
};
메시지 전송은 버튼을 클릭해도 되지만 enter key를 입력했을 때도 전송되도록 위와 같이 설정해두었다.
Try
키를 입력하면서 콘솔에 찍어봤는데 enter키가 두번 눌리는 것처럼 진행됨
그러면서 onSubmit() 함수도 중복 호출 됨!
처음엔 전송버튼을 직접 눌러서 전송하면 잘 가는데 enter를 눌러서 전송할때만 문제가 발생해서 enter key의 문제인가 싶어서 검색도 enter key 관련된걸로만 찾는데 해결방법을 못찾고있었는데 메시지를 보내다보니 ? ! 와 같이 마지막 글자가 특수문자면 정상적으로 전송이 되는 걸 발견했다.
한글한정 문제가 발생하는 것을 확인하고 바로 다시 검색해서 찾아보니
한글 관련한 중복 이슈는 해결방법들이 많이 올라와있었던 것 !
Solution
그 중에 보편적으로 사용하는 걸로 보이는 해결 방법을 적용해서 해결했다.
e.nativeEvent.isComposing
e.nativeEvent.isComposing를 이용해서 해결했음
const onEnter: KeyboardEventHandler<HTMLTextAreaElement> = (e) => {
console.log("e.key", e.key);
if (e.key === "Enter") {
console.log("onEnter");
console.log(content);
// console.log(e.key === "Enter", e);
if (e.shiftKey) {
return;
}
e.preventDefault();
if (!content?.trim()) {
return;
}
// 한글은 자음과 모음이 하나의 글자로 이루어져있기때문에
// 한글입력시 아직 조합중인지 끝났는지 판단할 수 없는경우에
// 마지막 글자가 하나 더 써지는 경우가 발생할 수 있음
// 조합중일때는 이벤트 전파를 막고,
// 끝난후에만 의도한 이벤를 한 번 실행시킨다.
if (e.nativeEvent.isComposing) {
onSubmit();
}
setContent("");
}
};
그래도 키가 찍히는 것을 확인해보면 아래와 같이 마지막 글자가 남긴한다
그래도 enter key를 눌렀을 때 onSubmit() 함수를 중복 호출하지 않고 setContent로 남는 한글도 지워주도록하여 정상작동하도록 만들었다.