今年、 Instagram Webの再編成中に、Reactコンポーネントを作成するときにES6 +の多くの機能を使用して楽しんでいます。 言語の新しい機能がReactアプリケーションの作成方法に影響を与え、このプロセスをこれまで以上に簡単で楽しいものにできる瞬間について詳しく説明します。
クラス
これまでのところ、ES6 +を使用したReactコンポーネントの記述方法で目に見える変化の中で最も顕著なのは、 クラス定義構文を使用することにしたことです。 React.createClassメソッドを使用してコンポーネントを定義する代わりに、 React.Componentクラスを拡張する実際のES6クラスを定義できます。
class Photo extends React.Component { render() { return <img alt={this.props.caption} src={this.props.src} />; } }
すぐにわずかな違いに気付くでしょう-クラス定義のより簡潔な構文が利用可能になります:
// The ES5 way var Photo = React.createClass({ handleDoubleTap: function(e) { … }, render: function() { … }, });
// The ES6+ way class Photo extends React.Component { handleDoubleTap(e) { … } render() { … } }
2つのブラケットと末尾のセミコロンを削除し、宣言されたメソッドごとに、コロン、キーワード関数、およびコンマを省略していることに注意してください。
予想どおり、新しいクラス定義構文を使用して、1つを除くすべてのコンポーネントライフサイクルメソッドを定義できます。 クラスコンストラクターは現在、以前に使用されたcomponentWillMountメソッドとして機能します 。
// The ES5 way var EmbedModal = React.createClass({ componentWillMount: function() { … }, });
// The ES6+ way class EmbedModal extends React.Component { constructor(props) { super(props); // Operations usually carried out in componentWillMount go here } }
プロパティ初期化子
ES6 +クラスの世界では、プロパティのタイプとデフォルト値はこのクラスの静的プロパティとして存在できます。 これらの変数とコンポーネントの初期状態は、ES7 プロパティ初期化子を使用して決定できます 。
// The ES5 way var Video = React.createClass({ getDefaultProps: function() { return { autoPlay: false, maxLoops: 10, }; }, getInitialState: function() { return { loopsRemaining: this.props.maxLoops, }; }, propTypes: { autoPlay: React.PropTypes.bool.isRequired, maxLoops: React.PropTypes.number.isRequired, posterFrameSrc: React.PropTypes.string.isRequired, videoSrc: React.PropTypes.string.isRequired, }, });
// The ES6+ way class Video extends React.Component { static defaultProps = { autoPlay: false, maxLoops: 10, } static propTypes = { autoPlay: React.PropTypes.bool.isRequired, maxLoops: React.PropTypes.number.isRequired, posterFrameSrc: React.PropTypes.string.isRequired, videoSrc: React.PropTypes.string.isRequired, } state = { loopsRemaining: this.props.maxLoops, } }
ES7プロパティ初期化子は、クラスコンストラクター内で機能します。 このコンストラクターでは、クラスを作成する前に、クラスの現在のインスタンスを参照します。 このため、コンポーネントの初期状態はthis.propsに依存する場合があります。 ゲッター関数に関してオブジェクトのデフォルトの小道具と初期状態を決定する必要がなくなったことは注目に値します。
矢印関数
React.createClassメソッドを使用して、コンポーネントインスタンスのメソッドへのバインドに関する追加作業を実行し、メソッド内でthisキーワードがコンポーネントインスタンスを参照するようにします。
// Autobinding, brought to you by React.createClass var PostInfo = React.createClass({ handleOptionsButtonClick: function(e) { // Here, 'this' refers to the component instance. this.setState({showOptionsModal: true}); }, });
React.createClassメソッドの使用に拘束されていないため、ES6 +クラスの構文を使用してコンポーネントを定義する場合、使用するインスタンスメソッドを手動でバインドする必要があるように思われます。
// Manually bind, wherever you need to class PostInfo extends React.Component { constructor(props) { super(props); // Manually bind this method to the component instance... this.handleOptionsButtonClick = this.handleOptionsButtonClick.bind(this); } handleOptionsButtonClick(e) { // ...to ensure that 'this' refers to the component instance here. this.setState({showOptionsModal: true}); } }
幸いなことに、2つのES6 + 機能 ( 矢印関数とプロパティ初期化子)を組み合わせることにより、コンポーネントインスタンスへのバインドを拒否することが非常に簡単になります。
class PostInfo extends React.Component { handleOptionsButtonClick = (e) => { this.setState({showOptionsModal: true}); } }
ES6矢印関数の本体は、それを囲むコードと同じ字句上のthisを使用します。 これにより、ES7プロパティ初期化子がスコープ内にあるため、望ましい結果を得ることができます。 これが機能する理由を確認するには、ボンネットの下を見てください。
動的プロパティ名とパターン文字列
オブジェクトリテラルの拡張機能の 1つに、派生名をプロパティに割り当てる機能が含まれます。 最初は、コンポーネントの状態の一部を設定するのと同様のことができます。
var Form = React.createClass({ onChange: function(inputName, e) { var stateToSet = {}; stateToSet[inputName + 'Value'] = e.target.value; this.setState(stateToSet); }, });
実行時にプロパティ名がJavaScript式によって決定されるオブジェクトを作成できるようになりました。 ここでは、 テンプレート文字列を使用して、コンポーネントの状態で設定するプロパティを決定します。
class Form extends React.Component { onChange(inputName, e) { this.setState({ [`${inputName}Value`]: e.target.value, }); } }
属性の分解と配布
多くの場合、コンポーネントを作成するときに、親コンポーネントのプロパティのほとんどを子コンポーネントに渡すことができますが、すべてではありません。 ES6 +デストラクチャリングと JSX 属性の配布の組み合わせで、これはタンバリンと踊ることなく可能になります:
class AutoloadingPostsGrid extends React.Component { render() { var { className, ...others, // contains all properties of this.props except for className } = this.props; return ( <div className={className}> <PostsGrid {...others} /> <button onClick={this.handleLoadMoreClick}>Load more</button> </div> ); } }
また、単純な優先度ルールを使用して値をオーバーライドし、属性値をデフォルトに設定することにより、JSX属性分布を通常の属性と組み合わせることができます。 this.propsに classNameプロパティが存在する場合でも、この要素はclassName属性のオーバーライドされた値を受け取ります。
<div {...this.props} className="override"> … </div>
classNameプロパティがthis.propsに存在しない場合、この要素のclassName属性はデフォルトで「base」に設定されます:
<div className="base" {...this.props}> … </div>
読んでくれてありがとう
私たちのように、ES6 +の機能を使用してReactコードを作成して楽しんでください。 この記事に貢献してくれた同僚に感謝します。また、今日私たち全員が未来にアクセスできるようにしてくれたバベルチームに感謝します。