Skip to main content
Zhimalab
中文

Fixing the Chinese Input Method Issue in the Word Dictation Tool

2025-12-06 · 14 min

Background

While developing the English word dictation tool, I found an input-method-related issue: when the user switched to a Chinese input method, they could type Chinese characters into the input box, which was not the intended behavior. The expected behavior is that regardless of the input method, only letters can be entered, and the experience should feel as smooth as using an English input method.

Problem analysis

  1. Locating the problem: in the WordDictation.jsx component, the input’s onChange handler didn’t validate incoming characters, so any character (including Chinese) could be entered.

  2. Root causes:

    • The input’s maxLength was set to 1, but the character type wasn’t restricted
    • The onChange handler accepted and processed all input without filtering characters
    • No regex validation existed to ensure only letters could be entered
  3. Extra findings:

    • Audio didn’t play on initial load (a condition-checking problem)
    • On initial load a mouse click was needed to start typing (an auto-focus problem)

The solution

1. Fixing the Chinese input method issue

Add letter validation to the input’s onChange handler, allowing only a-z and A-Z:

onChange={(e) => {
  const inputValue = e.target.value;
  // only allow letters
  if (/^[a-zA-Z]$/.test(inputValue)) {
    const newInput = userInput.split('');
    newInput[index] = inputValue.toLowerCase();
    const updatedInput = newInput.join('');
    setUserInput(updatedInput);
    
    // auto-focus the next input
    setTimeout(() => {
      if (inputValue && index < currentWord.word.length - 1) {
        const nextWrapper = e.target.parentElement.nextElementSibling;
        const nextInput = nextWrapper?.querySelector('input');
        if (nextInput) {
          nextInput.focus();
          nextInput.select();
        }
      }
    }, 0);
    
    // if all letters are entered, auto-trigger answer check
    if (updatedInput.length === currentWord.word.length && !showAnswer) {
      setTimeout(() => {
        checkAnswer();
      }, 300);
    }
  }
}}

2. Fixing the audio playback issue

Modify the audio playback useEffect condition so audio also plays on initial load:

useEffect(() => {
  if (currentWord) { // play audio as long as the current word exists
    const timer = setTimeout(() => {
      playWord();
    }, 150); // give state reset some time
      
    return () => clearTimeout(timer);
  }
}, [currentIndex, currentWord]);

3. Fixing the auto-focus issue

Optimize the auto-focus logic so the first input correctly receives focus on initial load:

useEffect(() => {
  // delay focus to ensure the DOM has rendered
  const timer = setTimeout(() => {
    if (!showAnswer) {
      // prefer focusing the first input via ref, ensuring focus on initial load
      if (inputRef.current && userInput.length === 0) {
        inputRef.current.focus();
      } else {
        // find the next position that should receive input
        const nextInputIndex = userInput.length;
        // use a more precise selector
        const inputs = document.querySelectorAll('.letter-input');
        const targetInput = inputs[Math.min(nextInputIndex, inputs.length - 1)];
        
        if (targetInput) {
          targetInput.focus();
          if (targetInput.value) {
             targetInput.select();
          }
        }
      }
    }
  }, 150); // increase the delay to ensure the DOM is fully rendered
  
  return () => clearTimeout(timer);
}, [currentIndex, isFullscreen, showAnswer, userInput.length]);

Result

  1. Input method issue resolved: even if the user switches to a Chinese input method, only letter characters can be typed, with no perceptible difference — it feels like using an English input method.

  2. Audio plays correctly: the current word’s audio auto-plays on initial load, and plays normally when switching words.

  3. Auto-focus works: on initial load focus automatically goes to the first input, so typing works without a mouse click — a better user experience.

Technical takeaways

  1. Input validation: use the regex /^[a-zA-Z]$/ for strict character validation, ensuring only letters can be entered.

  2. User experience optimization:

    • Auto-focus the next input to improve typing efficiency
    • Auto-trigger the answer check to reduce user actions
    • Keep consistent case handling to improve recognition accuracy
  3. State management: use the useEffect hook sensibly to handle component state changes and side effects.

  4. DOM operations: ensure operations run after the DOM is fully rendered to avoid problems from elements not yet loaded.

Summary

Through this fix, we resolved the input-method issue in the English word dictation tool, ensuring only letters can be entered regardless of the input method. We also optimized audio playback and auto-focus, improving the overall user experience.

The lessons from solving this problem:

  1. For input boxes, besides setting maxLength, also restrict the character type per requirements
  2. Regex is an effective tool for input validation — use it where appropriate
  3. Component state handling on initial load deserves special attention
  4. Auto-focus significantly improves UX and should be used in suitable scenarios

This fix not only solved the immediate problem but also provides reference experience for handling similar issues in the future.