フォーム
<input>、<textarea>、<option>のようなフォーム・コンポーネントは、 ユーザーの操作を通して変更される点で、他のネイティブなコンポーネントとは異なります。 これらのコンポーネントは、ユーザーの操作を受け取るフォームの管理を簡単にするためのインターフェースを提供します。
<form>上のイベントの情報については、フォームイベントを参照して下さい。
インタラクティブなprops
フォーム・コンポーネントは、ユーザーの操作に影響を受ける幾つかのpropsをサポートします。
-
value
は、<input>と<textarea>のコンポーネントにサポートされます。 -
checked
は、checkbox
またはradio
の型の<input>にサポートされます。 -
selected
は、<option>のコンポーネントにサポートされます。
全てのDOMイベントと同様、onChange
プロパティは全てのネイティブのコンポーネントにサポートされ、
バブルされるchangeイベントをリッスンするのに使用することが可能です。
制御された(Controlled)コンポーネント
valueが設定されている<input>は、制御されたコンポーネントです。 制御された<input>では、描画された要素の値は常にpropの値が反映されます。 例えば、
render: function() {
return <input type="text" value="Hello!" />;
}
これは、常にHello!
の値を持つinputが描画されます。
Reactにこの値はHello!
であると宣言されているため、
描画された要素に対するユーザー入力が反映されません。
もし、ユーザー入力の値を反映させたいのであれば、onChange
イベントを使用する必要があります。
getInitialState: function() {
return {value: 'Hello!'};
},
handleChange: function(event) {
this.setState({value: event.target.value});
},
render: function() {
var value = this.state.value;
return <input type="text" value={value} onChange={this.handleChange} />;
}
この例では、単純にユーザーによる最新の値を受け付け、<input>コンポーネントのprop値を更新します。 このパターンは、ユーザー操作に対する応答、または検証のインターフェース実装を簡単にしてくれます。 例えば、
handleChange: function(event) {
this.setState({value: event.target.value.substr(0, 140)});
}
これはユーザー入力を受け付けますが、先頭140文字に切り詰めます。
非制御(Uncontrolled)コンポーネント
value
が提供されない(または、それにnull
を設定する)<input>は、非制御コンポーネントです。
非制御の<input>では、描画された要素の値はユーザーの入力を反映します。
例えば、
render: function() {
return <input type="text" />;
}
これは、入力欄が空のinputが描画されます。
ユーザー入力は、描画された要素によって即座に反映されます。
もし、この値の更新をリッスンしたいのであれば、
制御されたコンポーネントと同様にonChange
イベントを使用して、それを行うことが可能です。
もし、空文字以外の値でコンポーネントを初期化したいのであれば、
defaultValue
のpropを提供することで、それが可能になります。
例えば、
render: function() {
return <input type="text" defaultValue="Hello!" />;
}
これは前述した制御されたコンポーネントとほぼ同じように機能します。
同じように、<input>はdefaultChecked
をサポートし、
<select>はdefaultValue
をサポートします。
一歩進んだ議論
何故、制御するのか?
Reactの<input>等のフォーム・コンポーネントは、 従来のHTMLフォームには無かった挑戦的な取り組みを行っています。 例えば、HTML内で、
<input type="text" name="title" value="Untitled" />
これはUntitled
の値で初期化されたinputを描画します。
ユーザーがinputを更新すると、このノードの値は変更されますが、
node.getAttribute('value')
をすると、まだ初期化時の値Untitled
を返します。
HTMLとは異なり、Reactは初期化時だけでなく、ある時点のビューのstateを表さなければいけません。 例えば、Reactであれば、
render: function() {
return <input type="text" name="title" value="Untitled" />;
}
このメソッドは任意の時点でのビューを表しているので、
このinputの値は常にUntitled
でなければいけません。
何故、textareaにvalueを持たせるのか?
HTMLでは<textarea>の値は、常にその子(ノード)を使用して設定されます。
<!-- 反例: このようにしないで下さい! -->
<textarea name="description">This is the description.</textarea>
HTMLであれば、開発者に対して簡単に複数行の値を提供してくれます。
ただし、ReactはJavaScriptであるため、文字列の制限が無く、
改行が必要であれば\n
を使用することが出来ます。
value
とdefaultValue
を持つReactのケースでは、子(ノード)の役割が曖昧になります。
こういった理由から、<textarea>の値を設定する際に子(ノード)を使用するべきではありません。
<textarea name="description" value="This is a description." />
もし、子(ノード)を使用すると決めた場合、それはdefaultValue
のように動作します。
何故、selectにvalueを持たせるのか?
HTMLでは、<select>の選択<option>は、
通常はoptionのselected
属性を通して指定されます。
Reactではコンポーネントにこの操作を簡単に行わせるために、代わりに下記のスタイルが適用されます。
<select value="B">
<option value="A">Apple</option>
<option value="B">Banana</option>
<option value="C">Cranberry</option>
</select>
非制御コンポーネントであれば、代わりにdefaultValue
を使用します。
value
属性に配列を渡すことで、
select
タグで複数のオプションを選択可能にすることが出来ます。
<select multiple={true} value={['B', 'C']}>