2015-05-01 18 views
11

Tôi đã viết mã này và hiện đang tranh cãi với một lỗi trong sự kiện onClick. Tôi có hai sự kiện, sự kiện onClick trên phần tử con và sự kiện onChange trên phần tử cha cấp cao nhất.ReactJS: "this.props" không phải là chức năng khi thành phần con gọi cho cha mẹ

Hành vi dự kiến ​​sẽ là thay đổi biến activeAccount hiện đang được giữ trong thành phần Vùng chứa. Để làm điều này, tôi đã thêm một trình xử lý onClick vào thành phần AccountRow mà sau đó sẽ gọi hàm onChange của cấp cao nhất của cha mẹ.

Tuy nhiên, dòng

'this.props.onChange(this.props.account)', 

trong

handleClick: function(e) { 
     this.props.onChange(this.props.account); 
    },  

có nghĩa là để gọi hàm với tham số cha mẹ 'this.props.account',

mang lại cho tôi lỗi này:

Uncaught TypeError: this.props.onChange is not a function. 

Tôi ban đầu nghĩ rằng đây là một vấn đề Phạm vi, nhưng tôi đã thêm

{...this.props} 

trên mọi trẻ em và con lồng nhau trong phụ huynh container thành phần. Vì vậy, tất cả các đạo cụ nên đã được tuyên truyền xuống thành phần AccountRow. Tuy nhiên, vấn đề vẫn còn.

var ACCOUNTS = [ 
    {name: 'cash on hand'}, 
    {name: 'savings account'}, 
    {name: 'shared account'}, 
    {name: 'my second wallet'} 
]; 

var TRANSACTIONS = [ 
    {date: '', name: 'Bananas', amount: 6, category: 'Groceries', account: 'cash on hand'}, 
    {date: '', name: 'Apples', amount: 2.50, category: 'Groceries', account: 'cash on hand'}, 
    {date: '', name: 'Cash withdrawal', amount: 250, account: 'savings account'} 
]; 

var AccountRow = React.createClass({ 

    handleClick: function(e) { 
     this.props.onChange(this.props.account); 
    }, 

    render: function() { 
     return (
      <li onClick = {this.handleClick}> {this.props.account}</li> 
     )} 
}); 

var AccountList = React.createClass({ 

    render: function() { 

     var rows = []; 
     this.props.accounts.map(function(each_account) { 
      rows.push(
       <AccountRow 
        account = {each_account.name} 
        key = {each_account.name} 
        {...this.props}  
       />); 
         }) 
    return (
     <ul> 
     {rows} 
     </ul> 
    ) 
    } 
}); 


var NavBar = React.createClass({ 

    render: function() { 
     return (
      <div id = 'account-tabs'> 
       <h2> Accounts </h2> 
       <AccountList 
        accounts = {this.props.accounts} 
        {...this.props} 
       /> 
      </div> 
     ) 
    } 
}); 

var TransactionRow = React.createClass({ 
    render: function(){ 
     var trans = this.props.transaction; 

     return (
      <tr> 
      <td>{trans.date}</td> 
      <td>{trans.name}</td> 
      <td>{trans.amount}</td> 
      <td>{trans.account}</td> 
      <td><a href = ''>edit</a></td> 
      </tr> 
     ) 
    } 
}); 

var TransactionList = React.createClass ({      
    render: function() { 

     var activeaccount = this.props.activeAccount; 

     var rows = []; 
     this.props.transactions.map(function(each_transaction) { 
      if (each_transaction.account == activeaccount) { 

       /* Very strange behaviour 
       if (each_transaction account == this.props.activeAccount) 
       DOES NOT WORK, I do not know why this is the case 
       */ 

       rows.push(<TransactionRow transaction = {each_transaction} key = {each_transaction.name} />); 
      } 
      else { 
       /*console.log(each_transaction.account);*/ 
      }  
     }) 
     return (
      <tbody> 
      {rows} 
      </tbody> 
     ) 
    } 
}); 

var TransactionsTable = React.createClass({ 
    render: function() { 

     return (
      <div id = 'recent-transactions'> 
      <h2>Recent Transactions for {this.props.activeAccount}</h2> 
      <table> 
       <tr> 
        <th>date</th> 
        <th>name</th> 
        <th>amount</th> 
        <th>account</th> 
        <th>edit </th> 
       </tr> 
       <TransactionList 
        transactions = {this.props.transactions} 
        activeAccount = {this.props.activeAccount} 
      /> 
      </table> 
      </div> 
     ) 
    } 
}); 

var TransactionForm = React.createClass({ 
    render: function() { 
     return (
      <div> 
      <h2>Add Transaction </h2> 
      <p>Transaction name</p> 
      <input type = 'text' /> 
      <p>Price</p> 
      <input type = 'number'/> 
      <p>Category (optional) </p> 
      <input type = 'text' /> 
      </div> 
     ) 
    } 
}); 


var ButtonMenu = React.createClass ({ 
    render: function() { 
     return (
      <div> 
      <button>Add Transaction</button> 
      </div> 
     ) 
    } 
}); 

var Container = React.createClass({ 

    getInitialState: function(){ 
     return { 
      activeAccount: ACCOUNTS[0].name 
     }; 
    }, 

    setActiveAccount: function(dat) { 
     this.setState({ 
      activeAccount: dat 
     }); 
    }, 

    render: function() { 
     return (
      <div id = 'wrapper'> 
      <NavBar 
       accounts = {ACCOUNTS} 
       activeAccount = {this.state.activeAccount} 
       onChange = {this.setActiveAccount} 
       {...this.props} 
      /> 
      <TransactionsTable 
       transactions = {TRANSACTIONS} 
       activeAccount = {this.state.activeAccount} 
      /> 
      <TransactionForm /> 
      <ButtonMenu /> 
      </div> 
     ); 
    } 
}); 


React.render(<Container />, document.body); 

Cảm ơn bạn đã dành thời gian.

+1

Bạn có chắc chắn 'this.props' thực sự có chức năng gọi lại' onChange' không? – skyline75489

+0

Tôi tin rằng tôi có nó trong thành phần , bên dưới hàm render của Container. –

Trả lời

9

Vấn đề là do map chức năng, bạn nên vượt qua trong this cho thisArg khi gọi map:

this.props.accounts.map(function(each_account) { 
    rows.push(
    <AccountRow 
     account = {each_account.name} 
     key = {each_account.name} 
     {...this.props}  
    />); 
}, this); 

Tuy nhiên, điều này sẽ gây ra AccountRow để có các biến không cần thiết như accountsactiveAccount. Tôi nghĩ bạn chỉ nên xem xét chuyển chức năng onChange:

<AccountRow 
    account = {each_account.name} 
    key = {each_account.name} 
    onChange = {this.props.onChange} 
/> 
+0

Bắt tốt! Làm cách nào để chuyển hàm 'onChange' xuống chuỗi? Tôi có tạo chức năng mới, chẳng hạn như '); ' sau đó gọi chức năng' onChange' cấp cao nhất? Hoặc là có một cách để vượt qua phương pháp 'onChange' thông qua đạo cụ? –

+0

Tôi đã chỉnh sửa câu trả lời. Hy vọng nó giúp. – skyline75489

+0

Cảm ơn sự giúp đỡ của bạn! Bạn có thể giải thích cách ', this' được thêm vào cuối hàm' rows.push' giúp giải quyết vấn đề này không? –

Các vấn đề liên quan