双方向バインディングヘルパー
ReactLink
は、Reactで双方向バインディングを簡単に表現するためのものです。
注意:
もし、このフレームワークの事をよく知らない場合は、
ReactLink
は、ほとんどのアプリケーションでは必要とされず、
慎重に扱わなければいけない事を知っておいて下さい。
Reactでは、データフローは所有者から子に対しての一方向になります。 これは、コンピューティングのノイマン型モデル(the Von Neumann model of computing)ではデータが一方向に流れるためです。(翻訳に自信なし) これを、"一方向のデータバインディング"と考えることが出来ます。
ただし、プログラムに返される何からのデータとフローを読むことが必要となるアプリケーションは数多く存在します。 例えば、ユーザーの入力を受け取り、あるReactのstateを頻繁に更新したいような開発スタイルの場合などです。 もしくは、JavaScriptでレイアウトを処理させる必要があり、Reactに何らかのDOM要素のサイズを変更させたいようなケースもあるかもしれません。
Reactでは、あなたは、"change"イベントをリッスンしてデータ・ソース(通常はDOM)から読み取り、
あなたのコンポーネントの1つからsetState()
を呼び出す事でこれを実装します。
"データフローのループを閉じる"ことで、より理解しやすく、保守がしやすいプログラムに導きます。
詳細については、フォームのドキュメントを参照して下さい。
双方向バインディング(Reactのstateを使用してDOM内の値を常に一定にすることで、暗黙的に強制します)は、
簡潔でアプリケーションのバリエーションを広げる事をサポートしてくれます。
我々は、前述した共通のデータフローのパターンを設定するためのシンタックスシュガー、
またはReactのstateへデータソースを"linking"(結合?)するReactLink
を提供します。
注意:
ReactLinkは、ただの薄いラッパーであり、onChange
/setState()
パターン周りの慣習に過ぎません。
これはReactアプリケーションのデータフローの基本的な流れ方を変えるものではありません。
ReactLink: ビフォー・アフター
下記はReactLink
を使用しない単純なフォームの例です。
var NoLink = React.createClass({
getInitialState: function() {
return {message: 'Hello!'};
},
handleChange: function(event) {
this.setState({message: event.target.value});
},
render: function() {
var message = this.state.message;
return <input type="text" value={message} onChange={this.handleChange} />;
}
});
これは問題なく動作し、データフローがとても見通しの良いものになりますが、
フォームのフィールドが多くなると、少し冗長になってしまいます。
ReactLink
を使用して、タイピングを減らしてみましょう。
var WithLink = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {message: 'Hello!'};
},
render: function() {
return <input type="text" valueLink={this.linkState('message')} />;
}
});
LinkedStateMixin
は、あなたのReactコンポーネントへlinkState()
と呼ばれるメソッドを追加します。
linkState()
は、Reactのstateの現在の値と、
それを変更するコールバックを含むReactLink
オブジェクトを返します。
ReactLink
オブジェクトはprops
として、そのツリーの上と下に渡すことが可能なため、
階層の深いコンポーネント間の双方向バインディングと、階層の高いstate
の設定が簡単(そして明確)になります。
チェックボックスは、チェックボックスがチェックされた際にフォームのsubmitに送られるvalue
属性に関係なく(デフォルトはon
)、
特別な振る舞いをすることに注意して下さい。
このvalue
属性は、チェックボックスがチェックされた際に、またはチェックが外された際に更新されません。
チェックボックスのために、valueLink
の代わりにcheckedLink
を使用する必要があります。
<input type="checkbox" checkedLink={this.linkState('booleanValue')} />
基盤部分
ReactLink
には2つの側面があり、1つはReactLink
インスタンスの作成、もう1つはそれの使用です。
ReactLink
がどのようにシンプルなのかを証明するために、
各側面から別々に書き換えて、より分かりやすいものにしてみましょう。
LinkedStateMixin無しのReactLink
var WithoutMixin = React.createClass({
getInitialState: function() {
return {message: 'Hello!'};
},
handleChange: function(newValue) {
this.setState({message: newValue});
},
render: function() {
var valueLink = {
value: this.state.message,
requestChange: this.handleChange
};
return <input type="text" valueLink={valueLink} />;
}
});
ご覧のように、
ReactLinkオブジェクトはvalue
とrequestChange
のプロパティを持つだけの非常にシンプルなオブジェクトです。
また、LinkedStateMixin
も同様にシンプルで、
this.state
とthis.setState()
を呼び出すコールバックから、
値と共にそれらのフィールドを生成します。
valueLink無しのReactLink
var WithoutLink = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {message: 'Hello!'};
},
render: function() {
var valueLink = this.linkState('message');
var handleChange = function(e) {
valueLink.requestChange(e.target.value);
};
return <input type="text" value={valueLink.value} onChange={handleChange} />;
}
});
valueLink
プロパティもまた同様に非常にシンプルです。
単純にonChange
イベントを扱い、this.props.valueLink.requestChange()
を呼び出し、
またthis.props.value
の代わりに、this.props.valueLink.value
も使用します。