双方向バインディングヘルパー
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も使用します。