Reactでフォーム要素を操作する基本と実践例

Reactは、動的でインタラクティブなWebアプリケーションを構築するために広く利用されているライブラリです。その中でもフォーム要素の扱いは、ユーザー入力を受け付け、アプリケーションの状態を管理する上で重要な役割を果たします。本記事では、Reactにおけるフォーム要素(input, textarea, select)の基本的な操作方法から、効率的なステート管理、イベントハンドリング、さらには実用的なバリデーションの実装までを順を追って解説します。初めてReactを触れる方でも理解しやすいように、具体例を用いて詳細に説明します。フォーム要素を正しく扱うスキルは、ユーザーフレンドリーで信頼性の高いアプリケーションを作成するために欠かせません。本記事を通じて、その基礎をしっかりと学びましょう。

目次

Reactのフォーム要素とは


フォーム要素は、Webアプリケーションでユーザーからの入力を受け取るための重要なUIコンポーネントです。Reactでは、これらの要素を効率的に管理し、アプリケーションのステートに結び付けることで、双方向のデータフローを実現します。

Reactで扱う主要なフォーム要素

1. input要素


単一行のテキスト入力やチェックボックス、ラジオボタンなど、さまざまな種類の入力を提供する要素です。

2. textarea要素


複数行のテキスト入力を受け付けるための要素で、ブログ投稿やコメントなどの長文入力に使われます。

3. select要素


ユーザーが複数のオプションから選択できるドロップダウンリストを提供します。

Reactにおけるフォーム要素の特性


Reactでは、フォーム要素を操作する際に主に2つの特性が重要です:

1. Controlled Components(制御されたコンポーネント)


フォームの値がReactのステートに完全に依存する形態で、リアルタイムの入力管理が可能です。

2. Uncontrolled Components(制御されていないコンポーネント)


フォームの値がDOMの内部状態に依存する形態で、直接的な参照を通じて値を取得します。

これらの特性を適切に活用することで、柔軟で効率的なフォーム操作を実現できます。次のセクションでは、ステートを用いたフォーム要素の管理方法について詳しく見ていきます。

フォーム要素におけるステート管理の基本


Reactでは、フォーム要素の値をアプリケーションの状態(ステート)で管理することが重要です。これにより、ユーザーの入力に基づいてリアクティブなUIを実現できます。

ステートで管理するメリット

1. リアルタイムの値反映


フォームの入力値が即座に画面上の他のコンポーネントや出力に反映されます。

2. 状態の一元管理


入力値をステートに保存することで、アプリケーション全体で値を共有・操作しやすくなります。

3. 簡単なバリデーション


ステートを活用することで、入力値の検証を効率的に行い、不正な入力を防ぐことができます。

基本的なステート管理の例

以下は、useStateフックを利用してinput要素を管理するシンプルな例です:

import React, { useState } from 'react';

function InputExample() {
  const [name, setName] = useState('');

  const handleChange = (event) => {
    setName(event.target.value);
  };

  return (
    <div>
      <label>
        名前:
        <input type="text" value={name} onChange={handleChange} />
      </label>
      <p>入力された名前: {name}</p>
    </div>
  );
}

export default InputExample;

コードの解説

  • useStateフックでnameというステートを定義し、初期値を空文字列に設定しています。
  • handleChange関数は、onChangeイベントによってトリガーされ、入力値を取得してステートを更新します。
  • value属性をnameにバインドすることで、フォーム要素の値が常にステートに同期されます。

ポイント

  • value属性を必ず指定することで、Controlled Componentとして動作させることができます。
  • 入力値の更新処理を明示的に記述することで、予測可能な挙動を保ちます。

次のセクションでは、Controlled ComponentsとUncontrolled Componentsの違いを詳しく解説します。

Controlled ComponentsとUncontrolled Components


Reactでフォーム要素を扱う際には、Controlled ComponentsUncontrolled Componentsという2つの異なるアプローチがあります。それぞれの特徴を理解し、適切なシナリオで使い分けることが重要です。

Controlled Components(制御されたコンポーネント)


Controlled Componentsとは、フォーム要素の値がReactのステートによって完全に制御されるコンポーネントを指します。

特徴

  1. 入力値はすべてReactのステートで管理されます。
  2. value属性を使用してフォームの現在の値を指定します。
  3. 入力の変更はイベントハンドラーを通じて行われます。

import React, { useState } from 'react';

function ControlledComponent() {
  const [inputValue, setInputValue] = useState('');

  const handleChange = (event) => {
    setInputValue(event.target.value);
  };

  return (
    <div>
      <label>
        入力:
        <input type="text" value={inputValue} onChange={handleChange} />
      </label>
      <p>現在の値: {inputValue}</p>
    </div>
  );
}

export default ControlledComponent;

メリット

  • ステートが信頼できるデータの唯一の情報源(Single Source of Truth)となる。
  • 入力検証や条件付きロジックが簡単に実装できる。

Uncontrolled Components(制御されていないコンポーネント)


Uncontrolled Componentsは、フォーム要素の値をDOMの内部状態で管理する方法です。

特徴

  1. Reactのステートを使用せず、値はDOMの中に保持されます。
  2. 入力値を取得する際にはrefを使用します。

import React, { useRef } from 'react';

function UncontrolledComponent() {
  const inputRef = useRef();

  const handleSubmit = (event) => {
    event.preventDefault();
    alert(`入力された値: ${inputRef.current.value}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        入力:
        <input type="text" ref={inputRef} />
      </label>
      <button type="submit">送信</button>
    </form>
  );
}

export default UncontrolledComponent;

メリット

  • 簡潔なコードでフォームの初期値や軽微な動作を実現できる。
  • 小規模なアプリケーションや単純なフォームに適している。

使い分けの指針

Controlled Componentsが適している場合

  • 複雑な入力検証が必要な場合。
  • 入力データを他のコンポーネントやAPIと連携させたい場合。

Uncontrolled Componentsが適している場合

  • 一時的な入力値を処理する小規模なフォーム。
  • ライブラリを使用してフォームを操作する場合(例:React Hook Form)。

次のセクションでは、input要素の実践的な使用方法を掘り下げて解説します。

input要素の実践的な使い方


Reactではinput要素を効率的に扱うことで、ユーザー入力に基づいた動的な動作を実現できます。ここでは、基本的な使用方法から実用的な応用例までを解説します。

基本的な使用方法


Reactでinput要素を使う場合、Controlled Componentとしてステートで値を管理するのが一般的です。

例: テキスト入力フォーム

import React, { useState } from 'react';

function BasicInput() {
  const [value, setValue] = useState('');

  const handleChange = (event) => {
    setValue(event.target.value);
  };

  return (
    <div>
      <label>
        名前:
        <input type="text" value={value} onChange={handleChange} />
      </label>
      <p>入力された名前: {value}</p>
    </div>
  );
}

export default BasicInput;

コードのポイント

  • value属性をステートにバインドすることで、フォーム要素とReactのステートが同期します。
  • onChangeイベントで入力値の変更を検知し、リアルタイムでステートを更新します。

チェックボックスの扱い方


type="checkbox"input要素を使うと、単純なオン/オフスイッチを実現できます。

例: チェックボックスの実装

import React, { useState } from 'react';

function CheckboxInput() {
  const [isChecked, setIsChecked] = useState(false);

  const handleCheckboxChange = (event) => {
    setIsChecked(event.target.checked);
  };

  return (
    <div>
      <label>
        チェックしてください:
        <input
          type="checkbox"
          checked={isChecked}
          onChange={handleCheckboxChange}
        />
      </label>
      <p>チェック状態: {isChecked ? 'オン' : 'オフ'}</p>
    </div>
  );
}

export default CheckboxInput;

コードのポイント

  • checked属性をステートにバインドして、チェック状態を同期させます。
  • onChangeイベントでチェック状態を取得します。

ラジオボタンの扱い方


複数の選択肢から1つを選ぶ場合、ラジオボタンを使用します。

例: ラジオボタンの実装

import React, { useState } from 'react';

function RadioInput() {
  const [selectedOption, setSelectedOption] = useState('');

  const handleRadioChange = (event) => {
    setSelectedOption(event.target.value);
  };

  return (
    <div>
      <h3>好きな色を選んでください:</h3>
      <label>
        赤
        <input
          type="radio"
          value="赤"
          checked={selectedOption === '赤'}
          onChange={handleRadioChange}
        />
      </label>
      <label>
        青
        <input
          type="radio"
          value="青"
          checked={selectedOption === '青'}
          onChange={handleRadioChange}
        />
      </label>
      <label>
        緑
        <input
          type="radio"
          value="緑"
          checked={selectedOption === '緑'}
          onChange={handleRadioChange}
        />
      </label>
      <p>選択された色: {selectedOption}</p>
    </div>
  );
}

export default RadioInput;

コードのポイント

  • 各ラジオボタンのvalue属性で選択肢を設定します。
  • 選択された値をステートに保存し、選択状態を同期します。

リアルタイムでの入力検証


input要素を使ってユーザー入力をリアルタイムで検証することも可能です。

例: 入力長さのリアルタイム検証

import React, { useState } from 'react';

function InputValidation() {
  const [text, setText] = useState('');
  const [error, setError] = useState('');

  const handleChange = (event) => {
    const inputValue = event.target.value;
    setText(inputValue);

    if (inputValue.length < 5) {
      setError('5文字以上入力してください。');
    } else {
      setError('');
    }
  };

  return (
    <div>
      <label>
        ユーザー名:
        <input type="text" value={text} onChange={handleChange} />
      </label>
      {error && <p style={{ color: 'red' }}>{error}</p>}
      <p>入力された文字数: {text.length}</p>
    </div>
  );
}

export default InputValidation;

コードのポイント

  • 入力値をリアルタイムでチェックし、条件を満たさない場合にエラーメッセージを表示します。
  • ユーザー体験を向上させるインタラクティブなフォーム設計が可能です。

次のセクションでは、textarea要素の扱い方について解説します。

textarea要素の特殊な扱い方


textarea要素は、複数行のテキスト入力を受け付けるためのフォーム要素です。Reactでtextareaを扱う際には、通常のinput要素と同様にステートを利用した管理が重要です。ただし、HTMLの標準的な動作と異なる点もあるため、注意が必要です。

Reactにおけるtextareaの基本


Reactでは、textareaのテキスト内容はvalue属性を使用して管理します。HTMLではテキスト内容をタグ内に記述しますが、ReactではControlled Componentの一部としてvalueをステートにバインドします。

例: 基本的なtextareaの使用

import React, { useState } from 'react';

function BasicTextarea() {
  const [text, setText] = useState('');

  const handleChange = (event) => {
    setText(event.target.value);
  };

  return (
    <div>
      <label>
        コメント:
        <textarea value={text} onChange={handleChange} rows="4" cols="50" />
      </label>
      <p>入力されたコメント:</p>
      <p>{text}</p>
    </div>
  );
}

export default BasicTextarea;

コードのポイント

  • value属性をステートにバインドして、textareaの値をReactのステートで管理します。
  • onChangeイベントでユーザー入力をリアルタイムに取得します。

textareaの初期値設定


Controlled Componentとして使用する場合、useStateの初期値でtextareaの初期値を設定できます。

例: 初期値が設定されたtextarea

import React, { useState } from 'react';

function PrepopulatedTextarea() {
  const [text, setText] = useState('このテキストが初期値です。');

  const handleChange = (event) => {
    setText(event.target.value);
  };

  return (
    <div>
      <label>
        コメント:
        <textarea value={text} onChange={handleChange} rows="4" cols="50" />
      </label>
    </div>
  );
}

export default PrepopulatedTextarea;

ポイント

  • 初期値がすでに含まれたフォームを提供することで、ユーザーにとって使いやすいUIを実現できます。

入力の制約や検証


長文を入力する際に文字数制限を設けることで、入力内容をコントロールできます。

例: 文字数制限付きtextarea

import React, { useState } from 'react';

function LimitedTextarea() {
  const [text, setText] = useState('');
  const maxLength = 100;

  const handleChange = (event) => {
    if (event.target.value.length <= maxLength) {
      setText(event.target.value);
    }
  };

  return (
    <div>
      <label>
        コメント (最大 {maxLength} 文字):
        <textarea value={text} onChange={handleChange} rows="4" cols="50" />
      </label>
      <p>{text.length}/{maxLength} 文字</p>
    </div>
  );
}

export default LimitedTextarea;

ポイント

  • event.target.value.lengthを利用して、リアルタイムで入力文字数を制御します。
  • 最大文字数を表示することで、ユーザーに直感的なフィードバックを提供します。

textareaの動的サイズ変更


ユーザーの入力に応じて、textareaのサイズを自動的に変更する方法も便利です。

例: 動的にサイズ変更されるtextarea

import React, { useState, useRef, useEffect } from 'react';

function AutoResizeTextarea() {
  const [text, setText] = useState('');
  const textareaRef = useRef(null);

  const handleChange = (event) => {
    setText(event.target.value);
  };

  useEffect(() => {
    if (textareaRef.current) {
      textareaRef.current.style.height = 'auto'; // 高さをリセット
      textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
    }
  }, [text]);

  return (
    <div>
      <label>
        コメント:
        <textarea
          ref={textareaRef}
          value={text}
          onChange={handleChange}
          rows="1"
          style={{ overflow: 'hidden', resize: 'none' }}
        />
      </label>
    </div>
  );
}

export default AutoResizeTextarea;

ポイント

  • scrollHeightを利用して、textareaの内容に応じた高さを動的に設定します。
  • ユーザー体験を向上させる柔軟なフォームを提供できます。

次のセクションでは、select要素の操作とオプションの管理方法について解説します。

select要素とオプションの管理


select要素は、複数の選択肢から1つまたは複数の値を選択できるフォーム要素です。Reactでselect要素を使用する場合、value属性をステートにバインドし、選択された値を効率的に管理します。また、動的にオプションを生成することで柔軟なフォームを構築できます。

基本的なselect要素の使用方法

例: シンプルな単一選択のselect要素

import React, { useState } from 'react';

function BasicSelect() {
  const [selectedOption, setSelectedOption] = useState('option1');

  const handleChange = (event) => {
    setSelectedOption(event.target.value);
  };

  return (
    <div>
      <label>
        選択してください:
        <select value={selectedOption} onChange={handleChange}>
          <option value="option1">オプション1</option>
          <option value="option2">オプション2</option>
          <option value="option3">オプション3</option>
        </select>
      </label>
      <p>選択された値: {selectedOption}</p>
    </div>
  );
}

export default BasicSelect;

コードのポイント

  • value属性をステートにバインドして、選択状態をReactのステートで管理します。
  • onChangeイベントで選択された値を取得してステートを更新します。

動的にオプションを生成する


オプションのリストを配列で管理し、動的に生成することで柔軟性を高められます。

例: 動的オプション生成

import React, { useState } from 'react';

function DynamicSelect() {
  const [selectedOption, setSelectedOption] = useState('');
  const options = ['赤', '青', '緑'];

  const handleChange = (event) => {
    setSelectedOption(event.target.value);
  };

  return (
    <div>
      <label>
        好きな色を選んでください:
        <select value={selectedOption} onChange={handleChange}>
          <option value="">選択してください</option>
          {options.map((color, index) => (
            <option key={index} value={color}>
              {color}
            </option>
          ))}
        </select>
      </label>
      <p>選択された色: {selectedOption}</p>
    </div>
  );
}

export default DynamicSelect;

コードのポイント

  • 配列optionsを使用して、mapメソッドでオプションを動的に生成します。
  • オプションリストを簡単に更新できるため、再利用性が高くなります。

複数選択(multi-select)の実装


multiple属性を利用して、複数の値を選択可能にすることもできます。

例: 複数選択のselect要素

import React, { useState } from 'react';

function MultiSelect() {
  const [selectedOptions, setSelectedOptions] = useState([]);

  const handleChange = (event) => {
    const selectedValues = Array.from(
      event.target.selectedOptions,
      (option) => option.value
    );
    setSelectedOptions(selectedValues);
  };

  return (
    <div>
      <label>
        好きな果物を選んでください:
        <select multiple value={selectedOptions} onChange={handleChange}>
          <option value="apple">りんご</option>
          <option value="banana">バナナ</option>
          <option value="cherry">さくらんぼ</option>
          <option value="date">デーツ</option>
        </select>
      </label>
      <p>選択された果物: {selectedOptions.join(', ')}</p>
    </div>
  );
}

export default MultiSelect;

コードのポイント

  • multiple属性を付けることで、複数選択が可能になります。
  • Array.fromを使用して選択された値を配列として取得します。

select要素の応用例


動的にオプションを追加するなど、ユーザーの入力に応じた柔軟なフォームを作成できます。

例: ユーザー入力に基づいてオプションを追加

import React, { useState } from 'react';

function AddOptionSelect() {
  const [options, setOptions] = useState(['オプション1', 'オプション2']);
  const [newOption, setNewOption] = useState('');
  const [selectedOption, setSelectedOption] = useState('');

  const handleAddOption = () => {
    if (newOption && !options.includes(newOption)) {
      setOptions([...options, newOption]);
      setNewOption('');
    }
  };

  const handleChange = (event) => {
    setSelectedOption(event.target.value);
  };

  return (
    <div>
      <label>
        オプションを選択してください:
        <select value={selectedOption} onChange={handleChange}>
          {options.map((option, index) => (
            <option key={index} value={option}>
              {option}
            </option>
          ))}
        </select>
      </label>
      <p>選択されたオプション: {selectedOption}</p>
      <input
        type="text"
        value={newOption}
        onChange={(e) => setNewOption(e.target.value)}
        placeholder="新しいオプション"
      />
      <button onClick={handleAddOption}>追加</button>
    </div>
  );
}

export default AddOptionSelect;

ポイント

  • 入力フィールドから新しいオプションを動的に追加できます。
  • 現在の選択肢にないオプションをリアルタイムで追加する柔軟なフォーム設計が可能です。

次のセクションでは、フォームの送信とイベントハンドリングについて解説します。

フォームの送信とイベントハンドリング


Reactでフォームを送信する際には、onSubmitイベントを使用してデータを処理します。フォームの送信は、ユーザー入力を収集し、必要に応じてサーバーにデータを送信する重要な役割を果たします。ここでは、基本的なフォーム送信の方法から、送信時のデータ処理までを解説します。

基本的なフォーム送信の方法

例: シンプルなフォーム送信

import React, { useState } from 'react';

function SimpleForm() {
  const [name, setName] = useState('');

  const handleSubmit = (event) => {
    event.preventDefault(); // ページリロードを防ぐ
    alert(`送信された名前: ${name}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        名前:
        <input
          type="text"
          value={name}
          onChange={(e) => setName(e.target.value)}
        />
      </label>
      <button type="submit">送信</button>
    </form>
  );
}

export default SimpleForm;

コードのポイント

  • onSubmitイベントを使用してフォーム送信時の処理を記述します。
  • event.preventDefault()を使用してデフォルトのフォーム送信(ページリロード)を防ぎます。

複数フィールドを持つフォームの管理


複数のフィールドを持つフォームでは、1つのステートオブジェクトでフォーム全体の状態を管理すると効率的です。

例: 複数フィールドのフォーム

import React, { useState } from 'react';

function MultiFieldForm() {
  const [formData, setFormData] = useState({
    username: '',
    email: '',
  });

  const handleChange = (event) => {
    const { name, value } = event.target;
    setFormData((prevData) => ({
      ...prevData,
      [name]: value,
    }));
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    alert(`送信されたデータ:\nユーザー名: ${formData.username}\nメール: ${formData.email}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        ユーザー名:
        <input
          type="text"
          name="username"
          value={formData.username}
          onChange={handleChange}
        />
      </label>
      <br />
      <label>
        メール:
        <input
          type="email"
          name="email"
          value={formData.email}
          onChange={handleChange}
        />
      </label>
      <br />
      <button type="submit">送信</button>
    </form>
  );
}

export default MultiFieldForm;

コードのポイント

  • name属性を使ってフォームフィールドを識別します。
  • formDataオブジェクトを使用して、複数のフィールドを一元管理します。

送信データの検証


送信時に入力データを検証し、不正なデータを送信させないようにすることが重要です。

例: データ検証付きフォーム

import React, { useState } from 'react';

function ValidatedForm() {
  const [email, setEmail] = useState('');
  const [error, setError] = useState('');

  const validateEmail = (email) => {
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); // 簡単なメールアドレス検証
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    if (!validateEmail(email)) {
      setError('正しいメールアドレスを入力してください。');
    } else {
      setError('');
      alert(`送信されたメールアドレス: ${email}`);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        メール:
        <input
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />
      </label>
      {error && <p style={{ color: 'red' }}>{error}</p>}
      <button type="submit">送信</button>
    </form>
  );
}

export default ValidatedForm;

コードのポイント

  • validateEmail関数でメールアドレスの形式を検証します。
  • エラーがある場合はメッセージを表示し、送信処理を中断します。

フォーム送信時のデータ送信(API連携)


フォーム送信時にデータをAPIに送信する場合には、fetchaxiosを使用します。

例: データをAPIに送信するフォーム

import React, { useState } from 'react';

function ApiForm() {
  const [username, setUsername] = useState('');
  const [status, setStatus] = useState('');

  const handleSubmit = async (event) => {
    event.preventDefault();
    try {
      const response = await fetch('https://example.com/api/users', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ username }),
      });

      if (response.ok) {
        setStatus('送信に成功しました!');
      } else {
        setStatus('送信に失敗しました。');
      }
    } catch (error) {
      setStatus('エラーが発生しました。');
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        ユーザー名:
        <input
          type="text"
          value={username}
          onChange={(e) => setUsername(e.target.value)}
        />
      </label>
      <button type="submit">送信</button>
      <p>{status}</p>
    </form>
  );
}

export default ApiForm;

コードのポイント

  • fetchを利用してデータをサーバーに送信します。
  • サーバーからのレスポンスに応じて、ステータスメッセージを表示します。

次のセクションでは、フォーム入力のバリデーションの基本と応用例について解説します。

バリデーションの基本と応用例


フォーム入力のバリデーションは、ユーザーが不正確なデータを送信しないようにするために重要です。Reactでは、ステートや関数を活用してクライアントサイドで柔軟にバリデーションを実装できます。ここでは、バリデーションの基本概念から、実用的な応用例までを紹介します。

バリデーションの基本


フォームの入力値が適切かどうかをチェックする基本的なバリデーションを行います。

例: 必須フィールドのチェック

import React, { useState } from 'react';

function RequiredFieldForm() {
  const [name, setName] = useState('');
  const [error, setError] = useState('');

  const handleSubmit = (event) => {
    event.preventDefault();
    if (!name) {
      setError('名前は必須項目です。');
    } else {
      setError('');
      alert(`送信された名前: ${name}`);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        名前:
        <input
          type="text"
          value={name}
          onChange={(e) => setName(e.target.value)}
        />
      </label>
      {error && <p style={{ color: 'red' }}>{error}</p>}
      <button type="submit">送信</button>
    </form>
  );
}

export default RequiredFieldForm;

ポイント

  • 必須入力のチェックをif (!name)で行います。
  • エラーがある場合はメッセージを表示し、送信を中断します。

リアルタイムバリデーション


リアルタイムで入力値をチェックすることで、ユーザーに即時フィードバックを提供します。

例: リアルタイムな入力長さの検証

import React, { useState } from 'react';

function RealTimeValidationForm() {
  const [inputValue, setInputValue] = useState('');
  const [error, setError] = useState('');

  const handleChange = (event) => {
    const value = event.target.value;
    setInputValue(value);

    if (value.length < 5) {
      setError('5文字以上入力してください。');
    } else {
      setError('');
    }
  };

  return (
    <div>
      <label>
        コメント:
        <input type="text" value={inputValue} onChange={handleChange} />
      </label>
      {error && <p style={{ color: 'red' }}>{error}</p>}
    </div>
  );
}

export default RealTimeValidationForm;

ポイント

  • handleChangeで入力値をリアルタイムに検証します。
  • エラーが発生した場合は即時にメッセージを表示します。

複数のフィールドを持つフォームのバリデーション


複数フィールドを持つフォームでは、フィールドごとにバリデーションを設定します。

例: メールとパスワードのバリデーション

import React, { useState } from 'react';

function MultiFieldValidationForm() {
  const [formData, setFormData] = useState({ email: '', password: '' });
  const [errors, setErrors] = useState({ email: '', password: '' });

  const validateForm = () => {
    const newErrors = {};
    if (!formData.email.includes('@')) {
      newErrors.email = '有効なメールアドレスを入力してください。';
    }
    if (formData.password.length < 6) {
      newErrors.password = 'パスワードは6文字以上必要です。';
    }
    return newErrors;
  };

  const handleChange = (event) => {
    const { name, value } = event.target;
    setFormData((prev) => ({ ...prev, [name]: value }));
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    const newErrors = validateForm();
    if (Object.keys(newErrors).length === 0) {
      alert('フォーム送信成功!');
    } else {
      setErrors(newErrors);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        メール:
        <input
          type="email"
          name="email"
          value={formData.email}
          onChange={handleChange}
        />
        {errors.email && <p style={{ color: 'red' }}>{errors.email}</p>}
      </label>
      <br />
      <label>
        パスワード:
        <input
          type="password"
          name="password"
          value={formData.password}
          onChange={handleChange}
        />
        {errors.password && <p style={{ color: 'red' }}>{errors.password}</p>}
      </label>
      <br />
      <button type="submit">送信</button>
    </form>
  );
}

export default MultiFieldValidationForm;

ポイント

  • 各フィールドごとにバリデーションエラーを管理するため、errorsオブジェクトを使用します。
  • validateForm関数で複数フィールドの検証ロジックを実装します。

応用: バリデーションライブラリの活用


複雑なバリデーションが必要な場合、YupFormikなどのライブラリを利用するのも効果的です。

例: Yupを使用したバリデーション

import React, { useState } from 'react';
import * as Yup from 'yup';

function YupValidationForm() {
  const [formData, setFormData] = useState({ email: '', password: '' });
  const [error, setError] = useState('');

  const schema = Yup.object().shape({
    email: Yup.string().email('有効なメールアドレスを入力してください。').required('メールは必須です。'),
    password: Yup.string().min(6, 'パスワードは6文字以上必要です。').required('パスワードは必須です。'),
  });

  const handleSubmit = async (event) => {
    event.preventDefault();
    try {
      await schema.validate(formData, { abortEarly: false });
      alert('送信成功!');
      setError('');
    } catch (validationError) {
      setError(validationError.errors.join(', '));
    }
  };

  const handleChange = (event) => {
    const { name, value } = event.target;
    setFormData((prev) => ({ ...prev, [name]: value }));
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        メール:
        <input
          type="email"
          name="email"
          value={formData.email}
          onChange={handleChange}
        />
      </label>
      <br />
      <label>
        パスワード:
        <input
          type="password"
          name="password"
          value={formData.password}
          onChange={handleChange}
        />
      </label>
      <br />
      {error && <p style={{ color: 'red' }}>{error}</p>}
      <button type="submit">送信</button>
    </form>
  );
}

export default YupValidationForm;

次のセクションでは、記事全体を振り返り、要点をまとめます。

まとめ


本記事では、Reactを使ったフォーム要素(input, textarea, select)の基本的な扱い方から、ステート管理、イベントハンドリング、そしてバリデーションの実装までを詳しく解説しました。

  • input要素では、テキスト入力やチェックボックス、ラジオボタンの動作を学びました。
  • textarea要素では、複数行入力の管理や動的サイズ変更の実装を行いました。
  • select要素では、動的オプション生成や複数選択の方法を理解しました。
  • 最後に、フォームの送信処理バリデーションの基礎および応用例を通じて、エラー防止の仕組みを習得しました。

これらの技術を活用することで、ユーザーフレンドリーで堅牢なフォームを作成できるようになります。Reactでフォーム操作のスキルをさらに深め、実践的なプロジェクトに挑戦してください。

コメント

コメントする

目次