propsの受け渡し
抽象的なコンポーネントを別のコンポーネントでラップすることは、Reactではよくあるパターンです。 外側のコンポーネントは、何らかの複雑な実装が行えるように、単純なプロパティを公開します。
JSXスプレッド属性を使用することで、追加の値と古いpropsをマージすることが出来ます。
<Component {...this.props} more="values" />
もしJSXを使用しないのであれば、ES6のObject.assign
、またはUnderscoreの_.extend
のような、
何らかのオブジェクト・ヘルパーを使用することが出来ます。
React.createElement(Component, Object.assign({}, this.props, { more: 'values' }));
以降のこのチュートリアルでは、ベスト・プラクティクスについて説明し、 これにはJSXと試験的なES7文法が使用されます。
手動での受け渡し
殆どの場合、プロパティを明示的に下の階層に向けて受け渡す必要があります。 これは、問題なく動作することが分かっている内部APIのサブセットだけにアクセスさせることを保証します。
var FancyCheckbox = React.createClass({
render: function() {
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
return (
<div className={fancyClass} onClick={this.props.onClick}>
{this.props.children}
</div>
);
}
});
React.render(
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
Hello world!
</FancyCheckbox>,
document.getElementById('example')
);
ただし、name
のプロパティ、title
のプロパティ、またはonMouseOver?
はどうなるのでしょうか?
JSX内での...を使用した受け渡し
注意:
下記の例において、--harmony
フラグはこの文法は試験的なES7であることを示すために必須となります。
もし、ブラウザ内JSX transformerを使用するのであれば、
<script type="text/jsx;harmony=true">
として下さい。
詳細については、後述するスプレッド・プロパティの...セクションを参照して下さい。
各プロパティをそれぞれ受け渡す事は、時に間違いやすく、うんざりさせられてしまいます。 そのようなケースでは、残りのプロパティに非構造化割り当て(destructuring assignment))を使用して、 未知のプロパティのセットを抽出することが出来ます。
残りの全てのプロパティが、...other
に出力されます。
var { checked, ...other } = this.props;
これは、自身で消費したものを除く全てのプロパティが受け渡されることを保証します。
var FancyCheckbox = React.createClass({
render: function() {
var { checked, ...other } = this.props;
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
// `other`は{ onClick: console.log }を含みますが、checkedプロパティは含みません。
return (
<div {...other} className={fancyClass} />
);
}
});
React.render(
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
Hello world!
</FancyCheckbox>,
document.getElementById('example')
);
注意:
上記の例では、checked
プロパティもまた正式なDOM属性です。
この非構造化割り当ての方法を使用しなかった場合、誤ってこれを渡してしまうかもしれません。
未知のother
プロパティを受け渡す際には、常に非構造化パターンを使用して下さい。
var FancyCheckbox = React.createClass({
render: function() {
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
// 悪い例: `checked`がそのまま内部コンポーネントに渡されてしまいます。
return (
<div {...this.props} className={fancyClass} />
);
}
});
全てのプロパティ渡しと同じプロパティの受け渡し
コンポーネントに全てのプロパティを使わせたいが、個別の受け渡しもしたいという場合は、
明示的にchecked={checked}
として再度受け渡すことが可能です。
これは、リファクタリング(refactor)とlintが容易になるため、
this.props
オブジェクトを全てそのまま受け渡す方が好ましいと言えます。
var FancyCheckbox = React.createClass({
render: function() {
var { checked, title, ...other } = this.props;
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
return (
<label>
<input {...other}
checked={checked}
className={fancyClass}
type="checkbox"
/>
{fancyTitle}
</label>
);
}
});
注意:
ここでは順序が重要になります。
あなたが指定するJSXのpropsの前に{...other}
置くことで、
コンポーネントのpropsがそれらJSXのpropsを上書き出来ないようにしています。
上記の例では、inputの型が"checkbox"
になる事を保証しています。
Restとスプレッド・プロパティ
Rest(...
)プロパティは、オブジェクトから新しいオブジェクトへ、残りのプロパティを抜き出す事を可能にしてくれます。
これは、非構造化(destructuring)パターン以外のプロパティを除きます。
下記は、ES7提案の試験的な実装です。
var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x; // 1
y; // 2
z; // { a: 3, b: 4 }
注意:
試験的なES7の文法を有効化するには、
JSXコマンドラインツールで--harmony
フラグを使用して下さい。
Underscoreを使用した受け渡し
JSXを使用しない場合でも、ライブラリを利用すれば同じパターンを使用することが可能になります。
Underscoreは出力プロパティをフィルタリングする_.omit
と、
新しいオブジェクトへプロパティをコピーする_.extend
をサポートします。
var FancyCheckbox = React.createClass({
render: function() {
var checked = this.props.checked;
var other = _.omit(this.props, 'checked');
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
return (
React.DOM.div(_.extend({}, other, { className: fancyClass }))
);
}
});