Skip to content
안녕하세요Enter ↵안녕하세요안녕하세요×2

Why Enter sends a chat message twice when typing Korean in a <textarea />

1 min readWorkMoved from my Tistory blogRead the Korean original

🧪 Code and reproducing the issue

I first built the chat input with the logic below.
When the user types a message in a <textarea /> and presses Enter, it sends the message and clears the input.

ts
const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {
  if (e.key === 'Enter' && !e.shiftKey) {
    e.preventDefault(); // prevent line break
    sendMessage(inputValue);
    setInputValue('');
  }
};
Figure 1. Reproduction GIF

When I typed "안녕하세요" ("hello") in Korean and pressed Enter,

  • the message was sent twice, or
  • only the last character, "요", was sent on its own, along with other strange behavior.

At first I thought handleSend() was being called twice, but when I looked closer, the cause was not inside the React code but in how the browser handles Korean input, the IME (Input Method Editor).

🤔 Why does this happen?

The cause of this problem is the Korean input method (IME).

What is an IME (Input Method Editor)?

It is the input method used to type composed characters, as in Korean, Japanese, and Chinese.

For example, if you type ㅇ, ㅏ, and ㄴ on the keyboard, the browser composes them and shows the character 안 (an).

During this process, the browser fires compositionstart, compositionend, and key events such as Enter multiple times.

The core of the problem

  • When the user composes Korean text and then presses Enter:
    1. an Enter event that commits the composition fires first, and
    2. then the actual Enter input event fires once more.

In other words, handleKeyDown is called twice, so the message is sent twice.

✅ The fix: check isComposing

React's KeyboardEvent object provides a property called e.nativeEvent.isComposing.

If this value is true, it means IME composition is in progress, so you just ignore Enter at that point.

🔧 Updated code

ts
const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {
  if (e.nativeEvent.isComposing) return; // ignore while Korean is being composed

  if (e.key === 'Enter' && !e.shiftKey) {
    e.preventDefault();
    handleSend();
  }
};
Figure 2. GIF of the fix

Now, even if you press Enter while typing Korean, the message is sent only once.

  • #Enter key runs twice
  • #IME
  • #Input Method Editor
  • #textarea

More in Work