티스토리 뷰

앱을 만들다 보면 우리 서비스가 원하는 "숫자만 입력 가능한 인풋"이라는 요구사항을 구현하기도 꽤나 고려할게 많다는 것을 느낀다.

input의 type속성을 number로 주면 되는데 무슨소린가?

-(마이너스)는 유효한 숫자로 인지하는 서비스인가? e(10의 제곱)를 유저로부터 허용할 것인가?

인풋 내에서 스크롤바를 통한 숫자의 증감을 허용할 것인가?

이런 세세한 요구사항들이 결합된 인풋이 필요해진다.

이런 요구사항을 가진 number type input을 두 번 만들면 곧 컴포넌트화 해야겠다는 생각이 든다.

const exceptThisSymbols = ['e', 'E', '+', '-', '.'];
const NumberInput = ({
  className,
  onChange,
  value,
  disabled,
}: NumberInputProps) => {
  return (
    <StyledInput
      type="number"
      className={className}
      onChange={onChange}
      onWheel={(e: any) => e.target.blur()}
      value={value}
      disabled={disabled}
      onKeyDown={(e) => {
        exceptThisSymbols.includes(e.key) && e.preventDefault();
      }}
    />
  );
};

const StyledInput = styled.input`
  padding: 0px 5px;
  &::-webkit-outer-spin-button,
  &::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
  }
`;
export default NumberInput;

우리 서비스에서는 스크롤바를 통한 숫자의 증감을 허용하지 않는다. 이런 경우 onWheeld이벤트를 사용하면 된다.

onWheel 이벤트가 발생하면 Blur 시켜서 포커스를 벗어나게 한다. 인풋의 숫자증감 포커스를 벗어나고

전체페이지의 스크롤로 초점이 옮겨가서 유저가 생각하는 스크롤이 된다. 

또한, e표기법도 사용하지 않으며 음수를 허용하지 않기 때문에 +,- 도 필요 없다.

onKeyDown이벤트를 사용해서 누른 키가 ['e', 'E', '+', '-', '.']에 해당하면 이벤트 발생을 방지해 준다.

input type number의 기본 이벤트가 방지되었다.

css로 증감 화살표 버튼도 안 보이게 처리했다.

 

근데 이상한 현상이 발생한다.

한글이 딱 한 글자씩 입력된다.

 

이것을 방지하기 위해 구글링을 해보면 onKeyUp이벤트를 이용하거나 e.nativeEvent를 이용하라는 글이 있는데

나의 경우에는 onKeyUp이벤트를 사용하는 방법도 안 됐고 한글이 입력될 때는 아예 이벤트 발생을 인지하지 못해서

e.nativeEvent가 발생하지도 않았다.

왜냐하면 input의 type속성이 number이기 때문에 한글을 이벤트로 인지하지 않는 것이다.

이런 예외들을 고려해서 코드를 하나씩 추가하는 것보다 type을 text로 두고 정규식을 통해 0~9까지만 허용하고

나머지는 그냥 return 시켜버리는 방법이 낫다.

const NumberInput = ({
  className,
  onChange,
  value,
  disabled,
}: NumberInputProps) => {
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (!numberOnlyReg.test(e.target.value)) return;
    if (onChange) onChange(e);
  };

  return (
    <StyledInput
      type="text"
      className={className}
      onChange={handleChange}
      value={value}
      disabled={disabled}
    />
  );
};

const StyledInput = styled.input`
  padding: 0px 5px;
`;
export default NumberInput;

숫자가 들어가는 Input은 <input type='number' />로 만든다. 가 서비스에 따라 정답은 아닐지도!

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함