2015-05-01 5 views
11

Ich habe diesen Code geschrieben und bin gerade mit einem Fehler in einem onClick-Ereignis beschäftigt. Ich habe zwei Ereignisse, das Ereignis onClick für das untergeordnete Element und das Ereignis onChange für das übergeordnete Element der obersten Ebene.ReactJS: "this.props" ist keine Funktion, wenn die untergeordnete Komponente das übergeordnete Element aufruft

Das erwartete Verhalten sollte sein, die activeAccount-Variable zu ändern, die derzeit in der Container-Komponente gehalten wird. Um dies zu tun, fügte ich einen OnClick-Handler für die AccountRow-Komponente hinzu, die dann die onChange-Funktion der übergeordneten übergeordneten Ebene aufrufen sollte.

jedoch die Linie

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

in

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

bedeutete die übergeordnete Funktion mit dem Parameter zu nennen 'this.props.account',

gibt mir diese Fehlermeldung:

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

Ich dachte zunächst, dass dies ein Scoping Problem war, aber ich habe

{...this.props} 

auf jedes Kind und verschachteltes Kind innerhalb der übergeordneten Containers Komponente hinzugefügt. Daher sollten alle Requisiten bis zur AccountRow-Komponente propagiert worden sein. Trotzdem bleibt das Problem bestehen.

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); 

Vielen Dank für Ihre Zeit.

+1

Sind Sie sicher, dass 'this.props' tatsächlich eine' onChange' Callback-Funktion hat? – skyline75489

+0

Ich glaube, ich habe es in der Komponente, unter Container Render-Funktion. –

Antwort

9

Das Problem wird durch map Funktion verursacht wird, sollten Sie in this für thisArg passieren, wenn map Aufruf:

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

, diese AccountRow verursachen redundante Variablen wie accounts und activeAccount haben. Ich denke, Sie sollten Transfer nur die onChange Funktion betrachten:

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

Guter Fang! Wie übergebe ich die "onChange" -Funktion in der Kette? Muss ich eine neue Funktion zu erstellen, wie ');' , die dann die oberste Ebene ruft 'onChange' Funktion? Oder gibt es eine Möglichkeit, die Methode onChange über Requisiten zu übergeben? –

+0

Ich habe die Antwort bearbeiten. Ich hoffe es hilft. – skyline75489

+0

Vielen Dank für Ihre Hilfe! Können Sie erklären, wie das am Ende der 'rows.push'-Funktion angehängte', this' hilft, dieses Problem zu lösen? –

Verwandte Themen