2016-05-12 19 views
1

私はFacebookのReact世界でかなり新しいです。彼らのドキュメントはとても良いようですが、ちょっとした明快さが必要な分野がいくつかあります。これはその一つです。ReactJSの "this"の謎

Srcは:http://tuts-javascript.appspot.com/reactjs-add-remove-table-row

var CompanyApp = React.createClass({ 
    getInitialState: function() { 
     return {companylist:this.props.companies}; 
    }, 
    handleNewRowSubmit: function(newcompany) { 
     this.setState({companylist: this.state.companylist.concat([newcompany])}); 
    }, 
    handleCompanyRemove: function(company) { 

     var index = -1; 
     var clength = this.state.companylist.length; 
     for(var i = 0; i < clength; i++) { 
      if(this.state.companylist[i].cname === company.cname) { 
       index = i; 
       break; 
      } 
     } 
     this.state.companylist.splice(index, 1); 
     this.setState({companylist: this.state.companylist}); 
    }, 
    render: function() { 
     var tableStyle = {width: '100%'}; 
     var leftTdStyle = {width: '50%',padding:'20px',verticalAlign: 'top'}; 
     var rightTdStyle = {width: '50%',padding:'20px',verticalAlign: 'top'}; 
     return ( 
     <table style={tableStyle}> 
      <tr> 
      <td style={leftTdStyle}> 
       <CompanyList clist={this.state.companylist} onCompanyRemove={this.handleCompanyRemove}/> 
      </td> 
      <td style={rightTdStyle}> 
       <NewRow onRowSubmit={this.handleNewRowSubmit}/> 
      </td> 
      </tr> 
     </table> 
    ); 
    } 
    }); 

    var CompanyList = React.createClass({ 
    handleCompanyRemove: function(company){ 
     this.props.onCompanyRemove(company); 
    }, 
    render: function() { 
     var companies = []; 
     var that = this; // TODO: Needs to find out why that = this made it work; Was getting error that onCompanyDelete is not undefined 
     this.props.clist.forEach(function(company) { 
     companies.push(<Company company={company} onCompanyDelete={that.handleCompanyRemove} />); 
     }); 
     return ( 
     <div> 
      <h3>List of Companies</h3> 
      <table className="table table-striped"> 
      <thead><tr><th>Company Name</th><th>Employees</th><th>Head Office</th><th>Action</th></tr></thead> 
      <tbody>{companies}</tbody> 
      </table> 
     </div> 
     ); 
    } 
    }); 

    var Company = React.createClass({ 
    handleRemoveCompany: function() { 
     this.props.onCompanyDelete(this.props.company); 
     return false; 
    }, 
    render: function() { 
     return (
     <tr> 
      <td>{this.props.company.cname}</td> 
      <td>{this.props.company.ecount}</td> 
      <td>{this.props.company.hoffice}</td> 
      <td><input type="button" className="btn btn-primary" value="Remove" onClick={this.handleRemoveCompany}/></td> 
     </tr> 
     ); 
    } 
    }); 

    var NewRow = React.createClass({ 
    handleSubmit: function() { 
     var cname = this.refs.cname.getDOMNode().value; 
     var ecount = this.refs.ecount.getDOMNode().value; 
     var hoffice = this.refs.hoffice.getDOMNode().value; 
     var newrow = {cname: cname, ecount: ecount, hoffice: hoffice }; 
     this.props.onRowSubmit(newrow); 

     this.refs.cname.getDOMNode().value = ''; 
     this.refs.ecount.getDOMNode().value = ''; 
     this.refs.hoffice.getDOMNode().value = ''; 
     return false; 
    }, 
    render: function() { 
     var inputStyle = {padding:'12px'} 
     return ( 
     <div className="well"> 
      <h3>Add A Company</h3> 
     <form onSubmit={this.handleSubmit}> 
      <div className="input-group input-group-lg" style={inputStyle}> 
      <input type="text" className="form-control col-md-8" placeholder="Company Name" ref="cname"/> 
      </div> 
      <div className="input-group input-group-lg" style={inputStyle}> 
      <input type="text" className="form-control col-md-8" placeholder="Employee Count" ref="ecount"/> 
      </div> 
      <div className="input-group input-group-lg" style={inputStyle}> 
      <input type="text" className="form-control col-md-8" placeholder="Headoffice" ref="hoffice"/> 
      </div> 
      <div className="input-group input-group-lg" style={inputStyle}> 
      <input type="submit" className="btn btn-primary" value="Add Company"/> 
      </div> 
     </form> 
     </div> 
     ); 
    } 
    }); 
    var defCompanies = [{cname:"Infosys Technologies",ecount:150000,hoffice:"Bangalore"},{cname:"TCS",ecount:140000,hoffice:"Mumbai"}]; 
    React.renderComponent(<CompanyApp companies={defCompanies}/>, document.getElementById("companyApp")); 

これはReactJSがどのように動作するかの非常に良い基本的な説明です。作者に感謝します。

しかし、このコメント

、この=

VAR。 // TODO:なぜこれでこれが機能するのかを知る必要があります。 onCompanyDeleteが定義されていないというエラーが発生しました

なぜそれが必要ですか? これは正しい方法ですか?そうでない場合は、何ですか?

ありがとうございます。

+2

これはReactにはあまり関係ありません。基本的なJSです。私は "JavaScriptのコンテキスト"のためのグーグルをお勧めしたい – ivarni

+0

それはもう必要ではない、そしてそれを行う正しい方法ではありません。要するに: – luschn

+0

@ luschn ..なぜあなたは「これはもう必要ではない」と言うだろうか? – Sachin

答えて

10

ReactJSに固有の「this」の謎はありません。

これは、JavaScriptでコールバックを含む標準的なスコープの問題の場合に過ぎません。

反応コンポーネントの場合、ベースコンポーネントのすべてのメソッドは、他のJavaScriptクラスと同様に、thisを現在のコンポーネントとしてスコープされます。

スニペットでは、renderメソッドがあります。これは基本コンポーネントの関数なので、thisはコンポーネント自体と同じです。しかしレンダリングメソッド内でthis.props.clist.forEachでコールバックを呼び出す場合、renderメソッド内の関数コールバックは、正しいthisスコープにバインドするか、またはvar that = this(これはアンチパターンですが推奨されません。 ) `。あなたが外で変数を定義する、または適切に結合のいずれかなしで直接thisを使用することはできません.forEachためのコールバックの内側に、上記のコメントから見ることができるように

var MyComponent = React.createClass({ 
    handleCompanyRemove: function(e) { 
     // ... 
    }, 
    render: function() { 
     // this === MyComponent within this scope 

     this.props.someArray.forEach(function(item) { 
      // this !== MyComponent, therefore this.handleCompanyRemove cannot 
      // be called! 
     }) 
    } 
}) 

:少しスニペットのバージョンを簡素化

例、関数。

これを解決するためのその他のオプションは以下のとおりです。正しいこの範囲にコールバック関数をバインド

。例:

this.props.someArray.forEach(function(item) { 
    // this === MyComponent within this scope too now! 
    // so you can call this.handleCompanyRemove with no problem 
}.bind(this)) 

あなたはバベル/ ES6を使用している場合は、thisスコープは、親スコープからのコールバックに続けていることを保証脂肪アロー関数の構文を使用することができます。例:

this.props.someArray.forEach((item) => { 
    // this === MyComponent within this scope too now! 
    // so you can call this.handleCompanyRemove with no problem 
}) 
+0

MDNによれば、 'forEach'に' this'のコンテキストを与えることもできます。例えばthis.props.someArray.forEach(function(item){}、this) 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach – peregrine42

+0

実際、しかしそれはforEachに固有のことです - 私は全てのコールバックにジェネリックにしようとしていましたが、彼の例でOPによって使われたようにforEachを使用しました。 –

+0

@MikeDriver ..ありがとう、答えの束。あなたはvar =これは落胆すべきだと言うので、これが問題を引き起こすと思われるシナリオはありますか? – Sachin