まくろぐ

React コンポーネントでフォームの入力を処理する

更新:
作成:

制御コンポーネント (controlled components)

React コンポーネントでフォームを構成する場合、コンポーネントの状態 (state) に基づいて表示を行うように実装すると、フォームの表示内容を制御しやすくなります。

/p/tdpybmw/img-001.png

このように、コンポーネントの表示内容が、完全にその状態 (state) によって決まるように実装されたものを、制御されたコンポーネント (controlled components) と呼びます。

このように設計することで、若干コード量は増えますが、表示内容を変更したいときはコンポーネントの state を変更するだけで済むようになります。 例えば、ネットワークから取得したデータをフォームに表示するような場合、そのフォームの構造を知る必要はなく、単純に state を更新するだけでよくなります。 これは、データとビューが分離された設計になっており、アプリ設計におけるベストプラクティスのひとつです。

input 要素の実装例

下記は、<input type="text"> 要素と <input type="submit"> 要素を持つ MessageForm コンポーネントの実装例です。 ユーザーがテキストを入力するたびに handleChange() が呼び出され、コンポーネントの状態 (state) が更新されます。 setState() の呼び出しにより state が変更が変更されると、再度 render() が実行され、表示内容が state の値に基づいて更新されます。

components/messageForm.tsx
import * as React from 'react';

interface IState {
  msg: string;
}

export class MessageForm extends React.Component<{}, IState> {
  constructor(props: {}) {
    super(props);
    this.state = {msg: ''};
  }

  // input 要素でのキー入力のたびに呼び出される
  private handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    this.setState({msg: event.target.value});
  }

  // submit ボタンを押したときに呼び出される
  private handleSubmit = (event: React.FormEvent) => {
    // submit ボタンのデフォルトの振る舞い (GET や POST) を抑制する
    event.preventDefault();

    // 実際にはここでメッセージ送信を行う
    // (送信内容は state を参照して取得すればよい)
    alert('次のメッセージが送信されました: ' + this.state.msg);
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          メッセージ:
          <input type="text" value={this.state.msg} onChange={this.handleChange} />
        </label>
        <input type="submit" value="送信" />
      </form>
    );
  }
}
index.tsx(使用例)
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { MessageForm } from './components/messageForm';

ReactDOM.render(<MessageForm />, document.getElementById('root'));

textarea 要素の実装例

テキスト入力領域として <textarea> 要素を使用する場合も、<input type="text"> 要素を使用する場合とほぼ同様に記述することができます。 ただし、イベントハンドラのパラメータの型は微妙に変わります(型パラメータとして HTMLInputElement ではなく、HTMLTextAreaElement を使用します)。

private handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
  this.setState({msg: event.target.value});
}

// ...

<textarea value={this.state.msg} onChange={this.handleChange} />

HTML の textarea 要素の値は次のように開始タグと終了タグの間に記述しましたが、

通常のHTMLの場合(参考)
<textarea>こんにちわ</textarea>

JSX の textarea の値は value プロパティで指定することに注意してください(input 要素と共通化されています)。

関連記事

まくろぐ
サイトマップまくへのメッセージ