【React】テキストのリアルタイムバリデーションと整形を両立する
こんにちはフロントエンドエンジニアの茶木です。
テキスト入力では、文字数チェックなどのリアルタイムのバリデーションをかけたいときがありますよね? 一方で、テキストの整形もしたいときもあります。両立するには、どのような実装ができるか考えます。
トリム自体は簡単
ここではテキストの整形はテキスト前後のトリムを行うとします。
トリムは string.trim()
で行ないます。空白や改行などあらゆるテキスト前後のホワイトスペースを削除するメソッドです。
onChange ごとのトリム
まず単純なトリム機能の追加を考えます。最初に思いつくのは onChange
のたびに整形後のテキストで値を更新する方法です。
const TrimForm = () => {
const [value, setValue] = useState("");
return (
<TextArea
value={value}
onChange={(e) => setValue(e.target.value.trim())}
/>
);
}
こちらコード的には問題なく機能するのですが、ユーザー的には使いにくいものになります。onChange
は入力ごとに発生するので、考えながら入力するようなフリーテキストであれば、書いている最中に改行やスペースが消されるのは不便です。
onBlur でのトリム
そこで便利なのが onChange
のかわりに onBlur
をトリガーにした整形です。
const TrimForm = () => {
const [value, setValue] = useState("");
return (
<TextArea
value={value}
onChange={(e) => setValue(e.target.value)}
onBlur={(e) => setValue(e.target.value.trim())}
/>
);
}
onBlur
にはテキストエリアがフォーカスを失ったときのコールバックが指定できます。onChange
と違い、入力中は発火しないのでユーザーが気にせず入力できます。
他のボタンをクリックして入力中のテキストを確定や送信するような場合について、補足します。
テキスト入力中に他のボタンを押すと、 まず、テキストエリアの blur イベントが発火したあと、ボタンの click や submit イベントが発火します。そのため、問題なくトリム後のテキストに対して、確定や送信の処理がなされます。
バリデーション
ここまでの実装で単純な整形はいけるのですが、ここからバリデーションを含む例を考えます。
結論からいうと、入力時にリアルタイムのバリデーションを逐次挟むケースでは工夫が必要です。テキストのバリデーションは登録・送信して良いかどうかのチェックなので、バリデーションは整形後のテキストに対して行う必要があります。
const TrimForm = () => {
const [value, setValue] = useState("");
const trimedValue = value.trim();
const error = validate(trimedValue);
return (
<TextArea
value={value}
onChange={(e} => setValue(e.target.value}
onBlur={(e) => setValue(trimedValue)}
error={error}
/>
);
}
このコードでは、value
が整形前で、trimedValue
が整形済み、 setValue
と連動して再レンダリングが行われるタイミングで trimedValue
も更新されます。
バリデーション用のメソッドには 整形済みテキストを渡し、入力値には整形前テキストを渡します。
おわりに
整形もバリデーションもそれぞれは単純なように見えて、組み合わせると複雑になります。ユーザー体験に繋がる部分なので、不便にならないように気をつけたい部分です。
Gaji-Laboでは、React経験が豊富なフロントエンドエンジニアを募集しています
弊社ではReactの知見で事業作りに貢献したいフロントエンドエンジニアを募集しています。大きな制作会社や事業会社とはひと味もふた味も違うGaji-Laboを味わいに来ませんか?
もちろん、一緒にお仕事をしてくださるパートナーさんも随時募集中です。まずはお気軽に声をかけてください。お仕事お問い合わせや採用への応募、共に大歓迎です!
求人応募してみる!