2016-07-07 9 views
-1

トップレベルのReactコンポーネントに、子コンポーネントのコールバックとして使用したいメソッドがたくさんあります。私はES6では、各メソッドのコンテキストを手動でバインドする必要があることを理解しています。私の現在のコンストラクタメソッドは次のようになります:コンストラクタ()内の多くのReactコンポーネントメソッドのコンテキストをバインドするための正しい規約は何ですか?

this.method1 = this.method1.bind(this); 
this.method2 = this.method2.bind(this); 
this.method3 = this.method3.bind(this); 
... 

これは動作します。コールバックを呼び出すたびに私の子供はすべて意図したコンテキストを保持することができますが、ES5で書く必要のないものを書くためのコードはたくさんあるようです。この定型文をすべて記述することなく、すべてのコンポーネントメソッドにコンテキストをバインドする簡単な方法はありますか?

+0

@naomikがダウンして削除のフラグが立っていても、私の答えを見ることをお勧めします。それはFacebookからの直接的な解決策であり、その理由を説明しています。 – mtaube

答えて

-1

Babelを使用している場合は、ステージ0を有効にして::このバインディング演算子を使用できます。

あなたは子供たちに渡すときに親コンテキストに結合することができるようになります。

method1() { 
    ... 
} 

render() { 
    return <ChildComponent method1={::this.method1} />; 
} 

https://babeljs.io/docs/plugins/preset-stage-0/
http://babeljs.io/docs/plugins/transform-function-bind/

+1

これは、 '' render''が呼び出されるたびにメソッドを束縛していることを意味していると思います。これは悪い習慣です。 – mtaube

+0

パフォーマンスの問題が発生しますか?彼の目的は、クラスのプロパティとして矢印関数でも達成できると思います。 –

0

私はES6で、私は手動で各コンテキストをバインドしなければならないことを理解し方法。

ええ、それは完全に真実ではありません。 ES6では、ES5の場合よりも多くのことを表現することができます。

あなたのコードをES6に書き込んだとしても、あなたが持っているコードをES5から直接翻訳するというわけではありません。現在のバージョンのReactの新機能やES6に固有の機能を使用して、それを行うための慣用的な方法があります。

import {Component} from 'react' 

class Foo extends Component { 
    // this class doesn't even need constructor 

    createButton(text) { 
    // don't write 
    // return <button onclick={this.handleClick.bind(this)}>{text}</button> 
    // instead write 
    return <button onclick={e=> this.handleClick(e)}>{text}</button> 
    } 

    handleClick(event) { 
    console.log(event, 'button was clicked') 
    } 

    render() { 
    var {buttons} = this.props; 
    // don't write 
    // return <div>{buttons.map(this.createButton.bind(this)}</div> 
    // instead write 
    return <div>{buttons.map(this.createButton, this)}</div> 
    } 
} 

export default Foo; 

// <Foo buttons={["one", "two", "three"]} /> 

お知らせ私は結合がほとんどのシナリオで必要とされていないため、字句thisを持ってFunction.prototype.bind

  1. アロー機能を必要としない2つの異なる方法でコンテキストを使用しました。矢印機能はES6の新機能です。
  2. Array.prototype機能forEachreducemapのようなあなたは、コールバックのコンテキストを変更することができますthisArgumentを受け入れます。これはES6には新しくないので、今日あなたのES5コードでこれを使用するのを止めるものは何もありません。

しかし、あなたはまた、これはstateless functional componentあると思いますか?ステートレス機能部品は、のように利用できる慣用的には0.14

がコードに反応反応して、あなたが書いたコンポーネントのほとんどは、単に他のコンポーネントを構成する、ステートレスになります。私たちは、あなたがレンダリングしたい要素を引数として小道具を取り、返すことができ、これらのコンポーネントのための新しい、簡単な構文を導入している

ソース:React Blog v0.14

このコードは機能的に同一でありますしかし、上記の構成要素には、このアプローチは、コンポーネントのために働くことはできませんもちろん何のclassまたはコンテキスト式典

const createButton = (text) => { 
    return <button onClick={handleClick}>{text}</button> 
} 

const handleClick = (event) => { 
    console.log(event, 'button was clicked') 
} 

// stateless functional component 
const Foo = ({buttons}) => { 
    return <div>{buttons.map(createButton)}</div> 
} 

export default Foo; 

を必要としない点I state(またはライフサイクルメソッド)ですが、これはほとんどのコンポーネントであるpropsを使用するコンポーネントすべてに適用されます。

これは、Function.prototype.bindを含まない慣用的な方法でリアクションアプリを書かなければならないもう1つの手法です。

何の価値があるのか​​、私はFunction.prototype.bind(私が書いたコードで)年に依存していません。

+0

矢印関数と配列プロトタイプ関数を使用して提案されているソリューションでは、複数回のバインディングが必要です。 React/Facebookはこれをおすすめしません。 [ドキュメントから](https://facebook.github.io/react/docs/reusable-components.html#es6-classes): "コンストラクタでイベントハンドラをバインドすることをお勧めします。すべてのインスタンス。これは、特に、子コンポーネントで浅い比較を使用してshouldComponentUpdate()を実装する場合は、アプリケーションのパフォーマンスにとって優れています。 – mtaube

-2

ここにはさまざまな有効なアプローチがあります。

import autobind from 'autobind-decorator'; 

class MyComponent extends React.Component { 
    @autobind 
    method1() { 
     // "this" is bound correctly 
    } 
} 

これはautobind-decoratorモジュール(または類似の機能を公開core-decorators)、プラスbabel-preset-decorators-legacyを必要とする:私が好む一方が@autobindデコレータを使用することです。

+1

デコレータモジュールは、バベル5からバベル6への簡単な移行を行うためにのみ存在し、現在のところデコレータは仕様の一部ではないことを明言しておく必要があります。 – naomik

+0

@naomik - もしあなたが 'decorators-legacy'プリセットを使用していれば、それは疑問です。BabelとES7が進化するにつれて、それはまだ動作します。仕様が整えば、デコレータパッケージは新しいAPIをサポートするように更新されるでしょう。 – nrabinowitz

関連する問題