Reactにおけるフォームのバリデーションと状態管理
はじめに
Reactアプリケーションを作る際に、ユーザーからの入力内容を管理し、その内容が有効なものであるかを確認するというのは一般的な実装の補足を行います。
全体のフロー
ユーザーがフォームの項目に入力を行うと、その情報は状態としてアプリケーションに保存されます。
そして、その入力内容はバリデーション(内容が有効であるかのチェック)を通過した上で、最終的に親コンポーネントに送られ、適切な処理が行われます。
コード例
resultステート
まず各フォーム項目の状態を保持するために、useState
フックを使用してresult
という状態を定義します。
const [result, setResult] = useState<Shop>(initialShop);
initialShop
とは、初期のShop
オブジェクト(またはその状態)を示す変数です。
ReactのuseState
フックで使われているこの変数は、状態の初期値を設定するために使われます。
const initialShop: Shop = { name: '', address: '', tel: '', // 他のプロパティ... };
こうすることで、アプリケーションが初期状態で読み込まれたとき、各フィールドは空の文字列として設定されます。それからユーザーがそれぞれのフィールドを編集すると、その状態が更新されていきます。
更新処理
フォームが送信されるときに行われる更新処理を見てみましょう。
const update = () => { if (validates()) { onUpdate(result); } };
ここでのonUpdate
は、親コンポーネントから渡される関数で、適切な更新処理を行うものとします。
validates
関数の戻り値がtrue
である場合、つまり全ての入力項目が有効である場合に限り、更新処理が行われます。
入力処理
ユーザーが入力を行ったときに状態を更新するためのonChange
関数を見てみましょう。
const onChange = (prop: string, value: string | number): void => { const update: Shop = { ...result, [prop]: value, } setResult(update); validate(prop, value as string); };
ここでは、更新したいプロパティ(例えば'name', 'address', 'tel'など)とその新しい値を引数として受け取り、result
の該当するプロパティの値を更新します。
更新は、スプレッド構文を使用することで展開と同一のプロパティが新しい値に書き換えられます。
setResultに更新後のプロパティを渡すことで状態が更新されます。
さらに、validate
関数を通じて入力項目が有効かどうかを確認します。
validate
validate関数では各プロパティに対するcase文でそれぞれバリデーション処理を担うのが一般的です。
関数の具体的な実装はそれぞれのプログラミング言語や使用するフレームワークによりますが、多くの場合、バリデーション関数は入力データが特定の要件を満たしているかどうかをチェックするために使用されます。
入力データの種類により、異なるバリデーションルールが適用される場合、switch
文(または、それに相当する構造)が使用されることはあります。
function validate(property, value) { switch(property) { case 'email': // Email validation logic here return validateEmail(value); case 'password': // Password validation logic here return validatePassword(value); case 'username': // Username validation logic here return validateUsername(value); default: return false; } }
大規模なアプリケーションや複雑なバリデーションロジックの場合、より柔軟で再利用可能なアプローチが推奨されます。
一例としては、オブジェクト指向の原則(多態性、継承など)を活用したバリデーションの設計があります。
バリデーションチェックを統括する
全ての項目が有効かどうかを確認します。
const validates = (): boolean => { const targets: (keyof Shop)[] = ['name', 'address', 'tel'] let countError = 0 validateErrors.clear() targets.forEach((target) => { countError += validate(target, (result[target] ?? '').toString()).length }) return !countError };
targets
という配列には、バリデーションを行いたい項目を設定します。
各項目についてバリデーションを実行し、エラーの数をカウントします。
全ての項目についてバリデーションを実行した後、エラーが存在しない(つまり全ての項目が有効である)場合にtrue
を返します。
このような手法はReactにおけるフォーム管理において一般的なもので、バリデーションと状態管理を同時に行うことで、ユーザーにとって使いやすいインターフェイスを提供します。
また、開発者にとってはコードが読みやすく、管理しやすいという利点もあります。
続く…
コメント
本記事の内容は以上になります!
プログラミングスクールのご紹介 (卒業生より)
お世話になったプログラミングスクールであるRUNTEQです♪
こちらのリンクを経由すると1万円引きになります。
RUNTEQを通じて開発学習の末、受託開発企業をご紹介いただき、現在も双方とご縁があります。
もし、興味がありましたらお気軽にコメントか、TwitterのDMでお声掛けください。