React で数値入力の検証を処理する最良の方法

WBOY
リリース: 2024-09-07 06:40:02
オリジナル
1171 人が閲覧しました

React で数値入力を処理するのは、特に数値が適切なサイズであることや小数点以下の桁数が適切であることを確認する必要がある場合に、面倒になることがあります。シンプルなものは簡単そうに見えますが、核心に迫り、カスタム ユーザー エクスペリエンスを実現しようとすると、コードはすぐに乱雑になる可能性があります。

ほとんどの人が使用する一般的なアプローチは、onChange ハンドラーでユーザー入力を制限するカスタム検証ロジックを作成することです。

こんな感じ

function NumberInput({
  value,
  onChange,
  min,
  max,
}: {
  value: number;
  onChange: (val: number) => void;
  min?: number;
  max?: number;
}) {
  const changeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
    const val = +e.target.value;
    if (min != null && val < min) {
      onChange(min);
      return;
    }
    if (max != null && val > max) {
      onChange(max);
      return;
    }
    onChange(val);
  };

  return (
    <input
      type="number"
      value={value}
      onChange={changeHandler}
    />
  );
}
ログイン後にコピー

このロジックは一見すると良さそうに見えますが、すでに試したことがある方は、予期せぬ奇妙な動作が多く発生し、ユーザー エクスペリエンスがまったく良くないことをご存知でしょう!

もう 1 つのアプローチは、標準 HTML を使用することです。 min、max、maxLength などの属性を使用した組み込みの検証を備えた要素。ただし、通常実装したい即時フィードバックや入力制限が欠けています。

結局、Google で Stack Overflow を検索し、いくつかの...ハッキング ソリューションを見つけます。

  • onKeyPress を使用して入力値を手動で検証します。
  • パターン属性を使用し、数値を検証する正規表現を追加します (これは type="number" では機能しないため、 type="text" にする必要があります)。
  • そしてそれ以外にも...

Best way to handle number input validation in React

多くの試行錯誤の後、最終的にこれを行うためのより良い方法を見つけ出しました。

解決策

組み込みの HTML 入力検証とカスタム JavaScript を利用して、完璧なソリューションを構築できます。

コンポーネントは次のとおりです

// Interface for props overriding the default value and onChange
// attribute to accept only numeric value
export interface NumberInputProps
  extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange"> {
  onChange: (val: number) => void;
  value: number;
}

function NumberInput({
  value,
  onChange,
  min,
  max,
  step,
  ...props
}: NumberInputProps) {
  // Internal input state to avoid weird behaviors with empty inputs
  const [input, setInput] = React.useState(value?.toString() || "");

  const changeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
    // Using HTML input validity API to validation
    if (
      (max != null && e.target.validity.rangeOverflow) ||
      (min != null && e.target.validity.rangeUnderflow) ||
      (step != null && e.target.validity.stepMismatch)
    )
      return;

    const val = +e.target.value;
    setInput(e.target.value);
    onChange(val);
  };

  // To ensure the external updates are reflected in the input element
  React.useEffect(() => {
    setInput(value.toString());
  }, [value]);

  return (
    <Input
      ref={ref}
      type="number"
      value={input}
      onChange={changeHandler}
      min={min}
      max={max}
      step={step}
      {...props}
    />
  );
}

ログイン後にコピー

このアプローチでは、組み込みの HTML 検証を利用し、無効なユーザー入力を制限することもできます。

Best way to handle number input validation in React

実際の例をチェックして試してみましょう

ボーナス

このロジックをカスタムフックで抽出することで、このロジックをより再利用しやすくすることができます

export const useNumberInput = ({
  value,
  onChange,
  min,
  max,
  step,
}: {
  value: number;
  onChange: (val: number) => void;
  max?: number;
  min?: number;
  step?: number;
}): InputHTMLAttributes<HTMLInputElement> => {
  const [input, setInput] = useState(value?.toString() || "");

  const changeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (
      (max != null && e.target.validity.rangeOverflow) ||
      (min != null && e.target.validity.rangeUnderflow) ||
      (step != null && e.target.validity.stepMismatch)
    )
      return;

    const val = +e.target.value;
    setInput(e.target.value);
    onChange(val);
  };

  useEffect(() => {
    setInput(value.toString());
  }, [value]);

  return {
    type: "number",
    value: input,
    onChange: changeHandler,
    min,
    max,
    step,
  };
};
ログイン後にコピー

必要に応じて任意のコンポーネントでそれを使用します (明らかに入力要素があるコンポーネントです)。

export default function CustomInput() {
  const [value, setValue] = useState(0);
  const inputProps = useNumberInput({
    value,
    onChange: setValue,
    min: 1,
    max: 50,
  });

  return (
    <div>
      <button onClick={() => onChange(value + 1)}>
        +
      </button>
      <button onClick={() => onChange(value - 1)}>
        -
      </button>
      <input
        {...inputProps}
        {...otherProps}
      />
    </div>
  );
}
ログイン後にコピー

お気軽にコメントを追加し、改善を提案してください!

以上がReact で数値入力の検証を処理する最良の方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート