2016-03-18 7 views
0

ich eine Benutzeroberfläche erstellen Reagieren bin mit und ich habe eine übergeordnete Komponente und eine untergeordnete Komponente, etwas in dieser Richtung:Reagieren: Kann Kind Requisiten im Eltern Event-Handler für den Zugriff auf

// Child component 
var ListItem = React.createClass({ 
    render: function() { 
    var link_details = (
     <div> 
      Start Date: {this.props.my_data.start_date}<br/> 
      End Date: {this.props.my_data.end_date}<br/> 
     </div> 
    ); 

    return (
     <li> 
      <a onClick={this.props.clickHandler}> 
      { this.props.my_data.name } 
      </a> 
      {link_details} 
     </li> 
    ) 
    } 
}); 

// Parent component 
var Sidebar = React.createClass({ 
    getInitialState: function() { 
    return { 
     my_data: [], 
    }; 
    }, 
    handleListItemClick: function(e){ 
    console.log(e.target); 
    console.log(e.target.props); 
    }, 
    render: function() { 
    var myLinks = this.state.my_data.map(function(mylink) { 
     return (
      <ListItem key={mylink.id} my_data={mylink} clickHandler={this.handleListItemClick} /> 
     ); 
    }.bind(this)); 
    return (
    <div> 
     <ul className="nav nav-sidebar"> 
     { myLinks } 
     </ul> 
    </div>) 
    } 
}); 

möchte ich den Klick Ereignis auf dem Kind, um den Handler des Elterns auszulösen, so dass das Elternteil seinen Zustand basierend auf dem, worauf im Kind geklickt wurde, aktualisieren kann. Während der Code, den ich oben habe, funktioniert, und der Handler des Elternteils aufgerufen wird, kann ich auf keine Requisiten der untergeordneten Komponente zugreifen. Ich bin nicht sicher, ob das von Entwurf ist und ich Daten auf andere Weise vom Kind zum Elternteil weiterleiten sollte, oder wenn ich etwas falsch mache. Ich bin immer noch sehr neu in React, daher ist jeder Rat gefragt. Vielen Dank!

Antwort

3

Sie können das nicht tun, aber Sie können

<li> 
    <a onClick={this.props.clickHandler.bind(null,this.props.my_data.name)}> 
    { this.props.my_data.name } 
    </a> 
    {link_details} 
</li> 

oder mit den Pfeilfunktion über Callback-Daten von Kind zu Eltern übergeben, wenn Sie es6

<li> 
    <a onClick={() => this.props.clickHandler(this.props.my_data.name)}> 
    { this.props.my_data.name } 
    </a> 
    {link_details} 
</li> 

bearbeiten

verwenden Warum Null übergeben?

Dinge zu erinnern: Automatische Bindung Methoden zu "this" passiert, wenn Ihre Komponente mounts.

Es gibt zwei Bedingungen

einen Rückruf von übergeordneten Komponente an eine untergeordnete Komponente übergeben 1.Calling

Wenn wir direkt Funktionen übergeben (zB this.clickHandler) zu einem Kind Komponente, ohne sich um die Sorgen Wert von 'dieser', wenn die Funktion tatsächlich aufgerufen wird.

reagieren dann die die Standard-Function.prototype.bind Methode mit einer eigenen Funktion ersetzt, Ihnen zu helfen zu verhindern, Dummheiten zu tun (wie der Versuch, die bereits gebundenen Wert von 'dieser ‚zu ändern), so dass Sie stattdessen passieren müssen‘ null 'zu sagen "Ich verstehe das wird nur die Argumente ändern".

2.eine Funktion definiert, innerhalb derselben Komponente

Reagieren Beim Aufruf dieser Funktion für nicht tun Anrufe innerhalb derselben Komponente

Regeln für

Bindung Wenn Sie .bind auf das erste Argument gesetzt werden soll durch den Aufruf eine Funktion ...

über Requisiten übergeben, übergeben Null als erstes Argument z

this.props.funcName.bind(null, "args") 

von 'this' übernommen, übergeben 'this' als erstes Argument z.

this.funcName.bind(this, "args") 
+0

Ich habe es versucht und obwohl es scheint zu funktionieren, erhalte ich eine Warnung in meiner Konsole: 'Warnung: bind(): Reagiere Komponentenmethoden können nur an die Komponenteninstanz gebunden werden.' Ändern der '.bind (this, this.props .my_data_name') zu '.bind (null, this.props.my_data_name)' beseitigt den Fehler, aber ich bin mir nicht sicher, was die Konsequenzen dieser Änderung sind. – Joseph

+0

'{this.props.clickHandler.bind (null, this.props.my_data_name)}} ist der richtige Weg, dies zu tun. – WitVault

+0

Bearbeitete die Antwort. – WitVault

1

Sie können dies tun:

var ListItem = React.createClass({ 
    clickItem: function (e) { 
     this.props.clickHandler(e, this.props.my_data); // now you can pass any data to parent 
    }, 
    render: function() { 
    var link_details = (
     <div> 
      Start Date: {this.props.my_data.start_date}<br/> 
      End Date: {this.props.my_data.end_date}<br/> 
     </div> 
    ); 

    return (
     <li> 
      <a onClick={this.clickItem}> 
      { this.props.my_data.name } 
      </a> 
      {link_details} 
     </li> 
    ) 
    } 
}); 
+0

Yup. Auch 'onClick = {() => this.clickHandler (this.props)}' – azium

+0

Interessante Weise, es zu tun, danke! Ich wäre neugierig, dies im Vergleich zu der Antwort zu sehen, die ich unten veröffentlicht habe. Ich denke, das ist etwas langwieriger (erfordert einen Event-Handler für das Kind und das Elternteil), und ich tendiere dazu, weniger Code zu schreiben, also bietet diese Antwort alles, was das andere nicht tut? – Joseph

+0

Ja. Im Gegensatz zu @ WitVaults Antwort erstellt diese Lösung keine neue Handler-Funktion bei jedem Render-Durchlauf. Die Funktion 'clickItem()' wird einmal instanziiert und dann unter allen 'ListItem'-Instanzen geteilt. Es sollte leistungsfähiger sein und weniger Speicher benötigen. – jdunning

0

Ich habe einen Blick auf die Antwort auf Pass props to parent component in React.js und kam mit den folgenden:

// Parent component 
var Sidebar = React.createClass({ 
    getInitialState: function() { 
    return { 
     my_data: [], 
    }; 
    }, 
    handleListItemClick: function(data_passed, e){ 
    console.log(data_passed); 
    }, 
    render: function() { 
    var myLinks = this.state.my_data.map(function(mylink) { 
     return (
      <ListItem key={mylink.id} my_data={mylink} clickHandler={this.handleListItemClick.bind(null, mylink.id)} /> 
     ); 
    }.bind(this)); 
    return (
    <div> 
     <ul className="nav nav-sidebar"> 
     { myLinks } 
     </ul> 
    </div>) 
    } 
}); 

Dies scheint ich arbeits würde interessieren andere Lösungen zu sehen und welche ist die "beste" und warum.

+0

Ja nicht das .. mach was @Dmitriy gesagt oder was ich in meinem Kommentar zu seiner Antwort gesagt habe. – azium

+0

Können Sie erklären warum "nicht das"? Was sind die Unterschiede? Warum ist dieser Weg schlecht? – Joseph

+1

1) Diese Lösung funktioniert, weil Sie den Wert wissen, den Sie im Voraus in Ihrem Elternteil haben möchten (die Artikel-ID). aber oft nicht ... also pass einfach die Requisiten von deinem Kind als Argument auf. viel häufiger. 2) Noch wichtiger ist, dass das Aufrufen von 'bind' innerhalb einer' render'-Methode eine Million neuer Funktionsinstanzen im Speicher hinzufügt. am besten, um nur eine normale Funktion zu verwenden – azium

Verwandte Themen