Knowledge Center
技術情報などを公開しています
en ja zh
React入門 全12回シリーズ

制御されたコンポーネントでフォームを構築(第8回)

By Author
image
フォームは、ユーザーからの入力を受け取り、データを処理するウェブアプリケーションの重要な要素です。Reactでは、制御されたコンポーネント(Controlled Components)を使用してフォーム入力を効率的に管理できます。本連載の第8回では、制御されたコンポーネントの基本を学び、フォームを構築してユーザー入力を処理する方法をハンズオン形式で習得します。第1回で構築したReact開発環境、第2回のJSX、第3回のProps、第4回の`useState`、第5回のイベントハンドリング、第6回のリストレンダリング、第7回の`useEffect`の知識を基に、macOS環境で開発を進めます。本記事は、プログラミングの基礎知識を持つ読者を対象としています。

制御されたコンポーネントの概念

制御されたコンポーネントは、フォーム要素の値がReactの状態(State)によって管理されるコンポーネントです。入力値はuseStateで管理され、value属性とonChangeイベントハンドラを組み合わせて状態と同期します。このアプローチにより、入力値の検証、変換、送信が容易になります。基本的な例は以下の通りです。

import React, { useState } from 'react';    
    
function Form() {    
  const [inputValue, setInputValue] = useState('');    
    
  return (    
    <input    
      type="text"    
      value={inputValue}    
      onChange={(e) => setInputValue(e.target.value)}    
    />    
  );    
}    

このコードでは、inputValue状態が<input>要素の値を管理し、onChangeで入力値を更新します。Reactが入力値を制御するため、状態とUIが常に同期します。

ハンズオン:シンプルなフォームの構築

制御されたコンポーネントの基本を理解するため、テキスト入力と送信ボタンを持つフォームを作成します。第1回で作成したプロジェクト(my-react-app)のsrc/App.jsを以下のように編集します。

import React, { useState } from 'react';    
import './App.css';    
    
function App() {    
  const [name, setName] = useState('');    
  const [message, setMessage] = useState('');    
    
  const handleSubmit = () => {    
    if (name.trim()) {    
      setMessage(`こんにちは、${name}さん!`);    
      setName('');    
    } else {    
      setMessage('名前を入力してください。');    
    }    
  };    
    
  return (    
    <div className="app-container">    
      <h1>シンプルなフォーム</h1>    
      <div>    
        <input    
          type="text"    
          value={name}    
          onChange={(e) => setName(e.target.value)}    
          placeholder="名前を入力"    
        />    
        <button onClick={handleSubmit}>送信</button>    
      </div>    
      <p>{message}</p>    
    </div>    
  );    
}    
    
export default App;    

このコードでは、name状態で入力値を管理し、handleSubmit関数で入力値を処理します。入力が空でない場合に挨拶メッセージを表示し、空の場合は警告メッセージを表示します。src/App.cssに以下のスタイルを追加して、フォームを見やすくします。

.app-container {    
  text-align: center;    
  padding: 20px;    
  font-family: Arial, sans-serif;    
}    
    
input {    
  padding: 8px;    
  margin: 10px;    
  font-size: 16px;    
}    
    
button {    
  padding: 10px 20px;    
  font-size: 16px;    
  cursor: pointer;    
}    

開発サーバー(npm start)が起動している状態で保存すると、ブラウザにフォームが表示されます。名前を入力して「送信」をクリックすると挨拶メッセージが表示され、空で送信すると警告が表示されます。この動作は、制御されたコンポーネントが状態と入力を同期させていることを示しています。

複数の入力フィールドの管理

実際のフォームでは、複数の入力フィールドを扱うことが一般的です。複数の状態を個別に管理する代わりに、オブジェクトを使用して効率的に管理できます。App.jsを以下のように変更し、名前とメールアドレスを扱うフォームを作成します。

import React, { useState } from 'react';    
import './App.css';    
    
function App() {    
  const [formData, setFormData] = useState({    
    name: '',    
    email: '',    
  });    
  const [message, setMessage] = useState('');    
    
  const handleChange = (e) => {    
    const { name, value } = e.target;    
    setFormData((prev) => ({    
      ...prev,    
      [name]: value,    
    }));    
  };    
    
  const handleSubmit = () => {    
    if (formData.name.trim() && formData.email.trim()) {    
      setMessage(`こんにちは、${formData.name}さん!メール: ${formData.email}`);    
      setFormData({ name: '', email: '' });    
    } else {    
      setMessage('すべてのフィールドを入力してください。');    
    }    
  };    
    
  return (    
    <div className="app-container">    
      <h1>複数フィールドのフォーム</h1>    
      <div>    
        <input    
          type="text"    
          name="name"    
          value={formData.name}    
          onChange={handleChange}    
          placeholder="名前を入力"    
        />    
        <input    
          type="email"    
          name="email"    
          value={formData.email}    
          onChange={handleChange}    
          placeholder="メールアドレスを入力"    
        />    
        <button onClick={handleSubmit}>送信</button>    
      </div>    
      <p>{message}</p>    
    </div>    
  );    
}    
    
export default App;    

このコードでは、formDataオブジェクトで複数の入力値を管理します。handleChange関数は、入力フィールドのname属性を使用して状態を動的に更新します。handleSubmitは、両方のフィールドが入力されている場合にメッセージを表示し、フォームをリセットします。ブラウザで確認すると、名前とメールアドレスを入力して「送信」をクリックすると、両方の値を含むメッセージが表示されます。

ハンズオン:フォームの拡張

制御されたコンポーネントの柔軟性を体感するため、読者自身でフォームをカスタマイズします。以下の課題を試してください。App.jsを編集し、入力された名前の文字数をリアルタイムで表示する機能を追加します。以下は一例です。

import React, { useState } from 'react';    
import './App.css';    
    
function App() {    
  const [formData, setFormData] = useState({    
    name: '',    
    email: '',    
  });    
  const [message, setMessage] = useState('');    
    
  const handleChange = (e) => {    
    const { name, value } = e.target;    
    setFormData((prev) => ({    
      ...prev,    
      [name]: value,    
    }));    
  };    
    
  const handleSubmit = () => {    
    if (formData.name.trim() && formData.email.trim()) {    
      setMessage(`こんにちは、${formData.name}さん!メール: ${formData.email}`);    
      setFormData({ name: '', email: '' });    
    } else {    
      setMessage('すべてのフィールドを入力してください。');    
    }    
  };    
    
  return (    
    <div className="app-container">    
      <h1>カスタムフォーム</h1>    
      <div>    
        <input    
          type="text"    
          name="name"    
          value={formData.name}    
          onChange={handleChange}    
          placeholder="名前を入力"    
        />    
        <p>名前の文字数: {formData.name.length}</p>    
        <input    
          type="email"    
          name="email"    
          value={formData.email}    
          onChange={handleChange}    
          placeholder="メールアドレスを入力"    
        />    
        <button onClick={handleSubmit}>送信</button>    
      </div>    
      <p>{message}</p>    
    </div>    
  );    
}    
    
export default App;    

このコードでは、名前の入力値の長さをリアルタイムで表示します。ブラウザで確認すると、名前を入力するたびに文字数が更新されます。自分で他の検証(例:メールアドレスの形式チェック)や入力フィールド(例:電話番号)を追加し、制御されたコンポーネントの活用方法を試してください。

次のステップに向けて

本記事では、制御されたコンポーネントを使用してフォームを構築し、ユーザー入力を効率的に管理する方法を学びました。フォームは、ユーザーとの対話を深める重要な要素です。第9回では、React Routerを使用してシングルページアプリケーション(SPA)のナビゲーションを実装する方法を学びます。これにより、複数のページをスムーズに切り替えるアプリケーションを構築できます。

おすすめの記事