2016-05-20 47 views
7

Sono davvero nuovo per React, e mi sto tirando fuori i capelli cercando di risolvere quello che mi sembra un problema semplice. Ecco una foto del componente che ho costruito.Comunicazione padre-figlio in React (JSX) senza flusso

Color Picking Component

Quello che sto cercando di realizzare sembra banale, ma letteralmente ogni articolo che ho letto che spiega cosa fare mi ha detto qualcosa di diverso, e non una delle soluzioni ha funzionato. Si riduce a questo: quando un utente fa clic su un tag, costruisce un vassoio e scorre attraverso una serie di colori per creare pulsanti colorati. Quando si fa clic su un pulsante colorato, è necessario passare a quale colore è stato fatto clic sul relativo componente principale ed eseguire una funzione per aggiornarne il colore. Ho letto di flusso, di eventi che ribollono, di legare "questo" a una proprietà e nessuna di queste soluzioni è sembrata funzionare. I documenti di React sono praticamente inutili per un principiante come me. Voglio evitare complicate strutture di eventi come il flusso a questo punto poiché sto aggiungendo alcuni componenti semplici a un'app esistente che non ho scritto in React in origine.

Inoltre, PS, questo codice è in JSX, il che per me è molto più sensato del semplice JS reagire. Grazie in anticipo per il vostro aiuto!

var colorsArray = ["#ED5851", "#9CCC64", "#337AEC", "#ff7a45", "#7E58C2", "#FFEB3B", "#78909C", "#FFFFFF", "#213a4b"]; 

var EditDrawer = React.createClass({ 
    updateColor: function() { 
     console.log("New Color: " + i); 
    }, 
    render: function(){ 
     var passTarget = this; 
     return (
      <div className="container-fluid animated fadeIn extra-fast-animation tag-edit-drawer"> 
       <div className="row"> 
        <div className="col-xs-12"> 
         {colorsArray.map(function(object, i){ 
          return <ColorButton buttonColor={object} key={i} />; 
         })} 
        </div> 
       </div> 
      </div> 
     ); 
    } 
}) 

var ColorButton = React.createClass({ 
    render: function(){ 
     var buttonStyle = { 
      backgroundColor: this.props.buttonColor, 
     }; 
     return (
      <div className="tag-edit-color-button" style={buttonStyle} > 
      </div> 
     ) 
    } 
}) 
+1

Come nota , ecco due tecniche che ho provato ad usare ma che non funzionavano. http://haochuan.io/how-to-communicate-between-pure-react-components-without-flux/ http://andrewhfarmer.com/component-communication/#3-callback-functions –

risposta

6

La funzione di callback dovrebbe funzionare. Come si è accennato nel commento precedente è possibile utilizzare il catturato this per accedere alla funzione updateColor dal bambino:

var passTarget = this; 
... 
... 
return <ColorButton 
    buttonColor={object} 
    key={i} 
    update={passTarget.updateColor} /> 

O come detto Bogdan si può passare attraverso carta dopo la vostra funzione di callback:

{colorsArray.map(function(object, i){ 
    return <ColorButton 
      buttonColor={object} 
      key={i} 
      update={this.updateColor} />; 
}, this)} 

Il componente <ColorButton /> dovrebbe quindi essere in grado di eseguire una semplice funzione onClick:

onClick={this.props.update} 

E allora si può semplicemente fare uso di obiettivi di eventi normali nel componente principale per catturare il colore del pulsante che è stato cliccato:

updateColor: function(e) { 
    console.log(e.target.style.backgroundColor); 
} 

Ecco un completo DEMO a manifestare.

+0

Sembra davvero promettente. Ho lasciato il lavoro per il fine settimana, ma lo controllerò la prossima settimana e lo aggiornerò qui. Grazie per l'aiuto! –

+0

Questo ha funzionato magnificamente, grazie mille per l'aiuto! –

3

Si può solo passare funzione di richiamata nel bambino dal componente principale, semplice come questo:

<ColorButton buttonColor={object} key={i} onColorSelect={this.updateColor}/> 

(quando si utilizza React.createClass tutti i metodi della classe sono già tenuti ad this, in modo che siano non richiesto per chiamare .bind(this)).

Quindi dal componente ColorButton è possibile chiamare questa richiamata come this.props.onColorSelect(...).

JS Bin esempio: http://jsbin.com/fivesorume/edit?js,output

+0

Grazie Bogdan ! Sfortunatamente ciò restituisce solo l'errore: "Impossibile leggere la proprietà 'updateColor' di undefined". Penso che sia perché sto eseguendo un ciclo attraverso un array e quindi "questo" viene sovrascritto. Per aggirare ho definito una variabile in precedenza per acquisire "questo" e questo mi permette di accedere alla funzione updateColor dal bambino. L'unico problema è che se cerco di passare qualcosa alla funzione, eseguirà la funzione nove volte sulla creazione anziché aspettare un clic. 'onClick = {this.props.onColorSelect (this.props.buttonColor)}' [visualizza questo] (http://imgur.com/hTFcUN3) –

+0

su come passare 'this' in Array.map - puoi anche passare come secondo argomento '.map (function ..., this)', allora sarebbe usato questo da scope esterno. Informazioni su 'onClick = {this.props.onColorSelect (this.props.buttonColor)}', non stai passando la funzione qui - la stai chiamando durante il rendering e passando il risultato. È necessario creare una funzione separata nel componente. –

+0

Questo ha molto senso. Farò un tentativo la prossima settimana. Grazie per l'aiuto! –

1

OK, questo è abbastanza semplice in Reagire senza usare flux o redux, simile al passaggio verso il basso puntelli da genitore a figlio, qui siamo in grado di utilizzare la funzione di callback come questo:

var colorsArray = ["#ED5851", "#9CCC64", "#337AEC", "#ff7a45", "#7E58C2", "#FFEB3B", "#78909C", "#FFFFFF", "#213a4b"]; 


var EditDrawer = React.createClass({ 
    updateColor: function(i) { 
     alert("New Color: " + i); 
    }, 
    render: function(){ 
     return (
      <div className="container-fluid animated fadeIn extra-fast-animation tag-edit-drawer"> 
       <div className="row"> 
        <div className="col-xs-12"> 
         {colorsArray.map(function(object, i){ 
          return <ColorButton buttonColor={object} key={i} updateColor={this.updateColor}/>; 
         }, this)} 
        </div> 
       </div> 
      </div> 
     ); 
    } 
}); 


var ColorButton = React.createClass({ 
    updateColor: function() { 
     this.props.updateColor(this.props.buttonColor); 
    }, 
    render: function(){ 
     var buttonStyle = { 
      backgroundColor: this.props.buttonColor, 
     }; 
     return (
      <div className="tag-edit-color-button" 
      style={buttonStyle} 
      onClick={this.updateColor}> 
       this.props.buttonColor 
      </div> 
     ) 
    } 
});