React.jsでフォームを扱う方法:制御コンポーネント(Controlled Components)徹底解説
通常のHTMLフォームでは、inputなどのフォーム要素が自身の値を内部的に保持しており、送信ボタンが押されたタイミングでまとめてデータが送信されます。
シンプルなHTMLフォームの例
<!DOCTYPE html>
<html>
<head>
<title>Form Example</title>
</head>
<body>
<form>
<label>
User Name:
<input type="text" name="username" />
</label>
<input type="submit" value="Submit Form" />
</form>
</body>
</html>上記の例では、usernameという名前のシンプルなテキスト入力欄があり、フォーム送信時に入力値を受け取ることができます。HTMLフォームのデフォルトの動作は、新しいページ(送信後のページ)へ遷移することです。
JavaScriptによるフォーム送信ハンドラのメリット
しかし、フォーム送信時に実行されるJavaScriptのハンドラ関数を用意すれば、送信前にフォームデータをバリデーション(検証)できるなど、より大きな利点が得られます。検証結果に応じてユーザーへ適切なフィードバックを返すことも可能です。
Reactにおける「制御コンポーネント」とは
Reactには、フォーム送信を扱うための「制御コンポーネント(Controlled Components)」という仕組みがあります。
HTMLでは、inputやtextareaなどの要素が自身の状態(state)を保持し、ユーザーの操作に応じて更新されます。一方、Reactではこのような変更可能なフィールドの値は、コンポーネントのstateオブジェクトで管理するのが基本です。これにより、入力値とUIの表示が常に同期され、単一のデータソースとしてstateを扱えます。
制御コンポーネントによるユーザー名入力の扱い方
class UserForm extends React.Component {
constructor(props) {
super(props);
this.state = {username: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({username: event.target.value});
}
handleSubmit(event) {
console.log('username: ' + this.state.username);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.username} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}ここでは、onChangeハンドラ関数を使って、入力のたびにstate内のusernameフィールドを更新しています。入力欄のvalueは常にstateから供給されるため、Reactがフォームの値を完全にコントロールできる状態になります。
フォーム送信時(onSubmit)には、送信されたユーザー名をブラウザのコンソールログに出力し、event.preventDefault()によってページ遷移のデフォルト動作をキャンセルしています。
その他の制御コンポーネントと非制御コンポーネント
制御コンポーネントとして扱えるのはinputだけでなく、textarea、selectタグ、ラジオボタンなども同様です。
一方で、ファイルアップロード用の<input type="file">のような非制御コンポーネント(Uncontrolled Components)も存在します。これらは読み取り専用の性質を持つため、フォーム送信時になって初めて値を受け取る形になります。
複数の入力項目を1つの関数で処理する方法
フォームの入力項目が複数ある場合も、各要素のname属性を利用すれば、1つのJavaScript関数でまとめて処理できます。
handleInputChange(event) {
const value = event.target.value;
const name = event.target.name;
this.setState({
[name]: value
});
}このようにES2015の算出プロパティ名(computed property names)を使えば、イベント発生元のnameに対応するstateキーを動的に更新でき、ハンドラ関数を共通化できます。
注意点:null値の入力欄を避ける
制御対象の入力欄にnull値を渡すことは避けるべきです。this.stateの初期化時に各フィールドへデフォルト値(空文字列など)を設定しておくことで、意図しない警告や挙動を防げます。
大規模なフォーム管理にはサードパーティ製ライブラリも有効
本格的なフォーム処理が必要な場合は、「Formik」などのサードパーティライブラリの活用がおすすめです。Formikを使えば、バリデーション、エラーメッセージの表示、ユーザーへのフィードバックなどをシンプルに実装でき、開発効率が大幅に向上します。
-
Pryで例外をスマートに扱う方法|バックトレース表示からカスタマイズまで
Rails開発者なら、Railsコンソールを頻繁に使う方も多いのではないでしょうか。そして今や、RailsコンソールといえばPryが定番。素のIRBと比べると、その使い勝手は段違いです。 実はPryには、例外を扱う際に非常に便利な機能が標準で組み込まれています。この記事では、その中でも特に役立つ3つの機能を紹介します。 直近の例外の完全なバックトレースを表示する Pry(IRBでも同様)で例外が発生すると、通常は短縮されたバックトレースが表示されます。多くの場合それで十分ですが、詳細を確認したい場面もありますよね。 そんなときは wtf -v コマンドを使いましょう。直近の例外の完全な
-
phpPress、goPress、rubyPress、nodePressでのお問い合わせフォーム実装ガイド
フラットファイルシステムで構築したウェブサイトで、ユーザーからのフィードバックを受け取りたいとします。DisqusのようなJavaScriptベースのコメントシステムを導入するのは簡単ですが、ここではユーザーが直接メールを送信し、それに個別に返信できる仕組みを作ります。 ブラウザ側だけで完結するJavaScriptのみのメール送信システムを作ることもできますが、ソースコードにメールアドレスが露見するとスパムボットに収集されてしまいます。したがって、メールアドレスはサーバー側で隠蔽する必要があります。 このチュートリアルでは、PressCMS(phpPress、goPress、rubyPress