<aside> 💡 React에선 onKeyDown → onKeyPress → onChange(value 변경됨) → onKeyUp(value 변경됨) 이벤트 순서대로 핸들러가 호출된다. 일반 자바스크립트에서 change 이벤트는 value 속성이 변경되고 포커스를 해제해야 호출되지만, React에선 Input 이벤트처럼 value 속성 값이 변경될 때마다 호출된다.
</aside>
onKeyDown
onKeyPress
이벤트는 핸들러 안에서 e.preventDefault()
메서드를 호출하면 입력을 막을 수 있다. 하지만 한글을 포함한 CJK 문자(조합 문자)는 메서드를 호출해도 그대로 입력된다. 이 방법은 숫자나 영어 입력을 막을때만 유효하다. 아래 방법으로 해결할 수 있다.
export default function App() {
const OnKeyDown = (e) => {
e.preventDefault();
};
return (
<div className="App">
<h1>Only allow numbers in input</h1>
<label>
<span className="label">Text Type</span>
<input type="text" onKeyDown={OnKeyDown} />
</label>
</div>
);
}
<aside>
💡 정규식에서 \\d
메타 문자는 10진수([0-9]
와 동일), \\D
는 10진수가 아닌 문자를 가리킨다
</aside>
onChange
이벤트가 발생하면 핸들러 안에서 숫자가 아닌 모든 value
를 빈문자열로 대체한다. onKeyDown
이벤트는 value
속성이 바뀌기 전에 호출하므로 사용할 수 없고, onKeyUp
이벤트는 한글(CJK 문자)이 지워지는 과정을 육안으로 확인 할 수 있어서 UX에 좋지 않다. 따라서 onChange
이벤트를 사용한다.
const onChange = (e) => {
// onChange 이벤트가 발생할 때마다 10진수가 아닌 문자를 모두 빈문자열로 대체
// 방향키, 백스페이스 등도 잘 작동한다
e.target.value = e.target.value.replaceAll(/\\D/g, "");
};
return (
<label>
<span className="label">Text Type</span>
<input type="text" onChange={onChange} />
</label>
);
onChange
이벤트가 발생해서 핸들러를 호출하는 시점엔 value
속성 값이 이미 바뀌어 있는 상태다. 예를들어 현재 Input에 88
이 입력된 상태에서 a
를 입력하면 핸들러 안에서 e.target.value
는 88a
가 된다.
정규식을 이용해서 e.target.value
에 10진수 문자만 있을때 상태를 변경하면 ➊숫자만 허용하면서 ➋불필요한 렌더링을 방지할 수 있다. value
속성 값이 변경된 후 onChange
이벤트를 제어하므로 방향키나 백스페이스 등은 모두 정상적으로 이용할 수 있다.
const [textValue, setTextValue] = useState("");
const onChange = (e) => {
// '88'.match(/\\D/g) -> null
// !'88'.match(/\\D/g) -> true -> 조건 통과 후 상태 변경
// '88a'.match(/\\D/g) -> ['a']
// !'88a'.match(/\\D/g) -> false -> 조건 통과 못해서 상태 변경 안함
if (!e.target.value.match(/\\D/g)) setTextValue(e.target.value);
};
return (
<label>
<span className="label">Text Type</span>
<input type="text" value={textValue} onChange={onChange} />
</label>
);
<input type="number" />
일 땐 기본적으로 숫자만 입력할 수 있다. 하지만 CJK 문자는 아래 이미지처럼 입력 필드에 그대로 표시되는 문제가 있다. number 타입 Input에서 CJK 문자 입력 방지는 생각보다 까다롭다.
CJK 조합 문자에서 조합을 시작했거나 조합중일 때 밑줄이 나타난다
일단 CJK 문자 입력은 onChange
onKeyPress
이벤트가 감지하지 못한다. 즉, 한글을 입력해도 핸들러가 호출되지 않는다. 대신 onKeyDown
onKeyUp
이벤트를 사용해야 CJK 문자 입력을 감지할 수 있다.