Skip to content

Instantly share code, notes, and snippets.

@FaviusTy
Created October 26, 2025 11:27
Show Gist options
  • Select an option

  • Save FaviusTy/0515b7fa8a2fa3860bf3390335ba4994 to your computer and use it in GitHub Desktop.

Select an option

Save FaviusTy/0515b7fa8a2fa3860bf3390335ba4994 to your computer and use it in GitHub Desktop.
MicrosoftIME利用時の未確定入力値の不正挿入の対応実装
import { memo, useCallback, useState } from "react";
export const Input = memo(function Input() {
const [composedValue, setComposedValue] = useState("");
const InputHandle = useCallback(
(e: React.InputEvent<HTMLInputElement>) => {
const { target } = e;
const { data, isComposing, inputType } = e.nativeEvent;
console.log(
"InputHandle",
"inputType:",
inputType,
"value:",
target.value,
"data:",
data,
"isComposing:",
isComposing,
"selectionStart:",
target.selectionStart,
"selectionEnd:",
target.selectionEnd,
"composedValue:",
composedValue
);
//MSIMEは変換確定せずにfocusoutした時にIMEの入力値が二重になってしまうため、composeEnd時に確保していた値で上書きする
if (
composedValue &&
inputType !== "deleteContentBackward" && //元の入力値次第でcomposeEnd直後のinsertTextの間にdeleteContentBackwardが入ることがあるため除外する
inputType !== "insertCompositionText" //insertCompositionTextはIMEモード中の入力値操作のため、ここも除外する
) {
console.log("set composedValue:", composedValue);
//NOTE: 直近入力値が半角数字の場合はEnterによる確定操作直後の可能性が高いため、composedValueをクリアするだけでvalueの上書きを行わない
if (/^[0-9]+$/.test(data)) {
return setComposedValue("");
}
e.target.value = composedValue;
setComposedValue("");
}
},
[composedValue, setComposedValue]
);
const FocusInHandle = useCallback(
(e: React.FocusEvent<HTMLInputElement>) => {
setComposedValue("");
e.target.select();
const { target } = e;
console.log(
"FocusInHandle",
"value:",
target.value,
"selectionStart:",
target.selectionStart,
"selectionEnd:",
target.selectionEnd
);
},
[setComposedValue]
);
const FocusOutHandle = useCallback(
(e: React.FocusEvent<HTMLInputElement>) => {
const { target } = e;
console.log(
"FocusOutHandle",
"value:",
target.value,
"selectionStart:",
target.selectionStart,
"selectionEnd:",
target.selectionEnd
);
//IMEモード中、きちんとEnterで変換確定操作を実施すると、onInputイベントは発生しないため、ここで確保していた値で上書きする
if (composedValue) {
console.log("set composedValue on blur:", composedValue);
e.target.value = composedValue;
}
setComposedValue("");
},
[composedValue, setComposedValue]
);
const CompositionStartHandle = useCallback(
(e: React.CompositionEvent<HTMLInputElement>) => {
const { target } = e;
console.log(
"CompositionStartHandle",
"value:",
target.value,
"selectionStart:",
target.selectionStart,
"selectionEnd:",
target.selectionEnd
);
},
[]
);
const CompositionEndHandle = useCallback(
(e: React.CompositionEvent<HTMLInputElement>) => {
const { target } = e;
console.log(
"CompositionEndHandle",
"value:",
target.value,
"selectionStart:",
target.selectionStart,
"selectionEnd:",
target.selectionEnd
);
setComposedValue(target.value);
},
[setComposedValue]
);
return (
<input
defaultValue={1234}
onInput={InputHandle}
onFocus={FocusInHandle}
onBlur={FocusOutHandle}
onCompositionStart={CompositionStartHandle}
onCompositionEnd={CompositionEndHandle}
/>
);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment