2015-05-24 18 views
7

Ho un app react.js con struttura come questa:React.js Come passare eventi attraverso componenti figlio multipli?

<CalcApp /> --- root component, state is set here 
    <CalcTable /> --- 1st child component 
    <CalcRow /> --- 2nd child component 
     - input onChange event 

voglio essere in grado di ascoltare un un evento onChange accadendo all'interno del -CalcRow-> componente <, ma sto avendo difficoltà passare il evento fino al componente root.

Ho guardato in giro per il web e lo stackoverflow, abbastanza estesamente, ma non ho trovato esempi su come farlo.

Qual è il modo migliore per passare l'evento da un componente figlio profondamente annidato fino al componente radice in modo che possa cambiare stato?

Ecco il mio codice completo:

var React = window.React = require('react'), 
// include external components from ui folder like the exmaple blow: 
// Timer = require("./ui/Timer"), 
    Timer = require("./ui/Timer"), 
    mountNode = document.getElementById("app"); 

var catOne = [ 
    {name : 'one', value : 5, key : 1}, 
    {name : 'two', value : 2, key : 2}, 
    {name : 'three', value : 3, key : 3} 
     ]; 

var CalcTable = React.createClass({ 
    changeHandler: function(){ 
    console.log('ding'); 
    this.props.onChange(); 
    }, 
    render: function() { 
    var rows = []; 

    // var myVar = this.props.cat1;  

    this.props.cat1.forEach(function(item){ 
     rows.push(<CalcRow item={item} ref="row" key={item.key} onChange={this.changeHandler} />); 
    }); 
    return(
     <table>{rows}</table> 
    ) 
    } 
}); 

var CalcRow = React.createClass({ 
    changeHandler: function(e) { 
     console.log('ping'); 
     this.props.onChange(); 
    }, 
    render: function(){ 
    return(
     <tr> 
      <td>h</td> 
      <td>{this.props.item.name}</td> 
      <td><input cat1={this.props.item} value={this.props.item.value} name={this.props.item.key} onChange={this.changeHandler} /></td> 
     </tr> 
    ) 
    } 
}); 

var AddRowButton = React.createClass({ 
    handleSubmit: function(e) { 
     e.preventDefault(); 
     this.props.onSubmit(this); 
    }, 
    render: function(){ 
    return(
     <form onSubmit={this.handleSubmit}> 
      <input /> 
      <button>Add</button> 
     </form> 
    ) 
    } 
}); 

var SectionSummary = React.createClass({ 
    render: function(){ 
    return(
    <div className="summary"> 
     <div className="table-summary"> 
     stuff 
     </div> 

    </div> 
    ); 
    } 
}); 

var CalcApp = React.createClass({ 
     changeHandler: function(e) { 
     console.log('bong'); 
    }, 
    getInitialState: function(){ 
    return { 
     cat1: this.props.cat1 
     }; 
    }, 
    handleSubmit: function() { 
     // console.log(this.props.cat1); 
     // console.log(this.props.cat1.length+1); 
     var newKeyVal = this.props.cat1.length+1; 
     c = this.props.cat1; 
     c = c.push({name : "four", value : 4, key : newKeyVal}); 
     this.setState({ 
     cat1:c 
     }); 
     // console.log(this.state.cat1); 
    }, 
    render: function() { 
    return (
     <div> 
      <h3>title</h3> 
      <CalcTable cat1={this.props.cat1} onChange={this.changeHandler}/> 
     <div className="stuff"><p>stuff</p></div> 
     <div className="stuff"> 
      <AddRowButton cat1={this.props.cat1} onSubmit={this.handleSubmit}/> 
      </div> 
      <SectionSummary /> 
     </div> 
    ); 
    } 
}); 

React.render(<CalcApp cat1={catOne}/>, mountNode); 

risposta

1

Una soluzione può essere quella di utilizzare un dispatcher evento comune.

nel componente genitore, si dovrebbe scrivere

var dispatcher = require('./my-dispatcher') 
dispatcher.on('my.event', function (e, myArg) { 
    // do some stuff here 
}) 

e nel bambino

var dispatcher = require('./my-dispatcher') 
dispatcher.trigger('my.event', 'my arg value') 

Se non si desidera implementare il dispatcher da soli, ci sono alcune biblioteche di tutto. Non l'ho provato, ma per esempio https://github.com/mrdoob/eventdispatcher.js/ sembra fare questo lavoro.

+0

grazie sto cercando in questo – psvj

+0

Ci sono alcune informazioni più estese su questo sul sito di flusso di Facebook. https: //facebook.github.io/flux/docs/dispatcher.html –

+0

Nel caso in cui qualcuno in una situazione simile lo legga, ho finito per implementare l'architettura del flusso usando reflusso, poiché sembrava essere la più semplice implementazione del flusso. – psvj

1

Uso PubSubJS per comunicare tra i miei componenti React ... in questo modo si mantiene tutto indipendente l'uno dall'altro e non strettamente collegati.

Si può leggere di più su PubSubJS qui: https://github.com/mroderick/PubSubJS

di comunicare, un componente pubblicare e ogni abbonato sarà possibile ottenere i dati.

ho imparato su questo da questo blog: http://maketea.co.uk/2014/03/05/building-robust-web-apps-with-react-part-1.html#component-communication

Lui sta usando window.addEventListener ma io non lo consiglio in quanto non tutti i browser lo supporta, oltre alla PubSubJS è molto più facile da implementare.

4

Solo una parola di cautela quando si utilizza pub/sub: È troppo facile andare fuori bordo con gli eventi. All'inizio sembra che risolva tutti i problemi che tu abbia mai avuto. Poi dopo un po 'ti accorgi che tutto il tuo codice è una palla aggrovigliata di spaghetti-evento.

Gli eventi sono un po 'come i globali in quanto tendono a rendere tutto migliore fino a rendere tutto peggiore. E quando finisci dove fanno tutto peggio, è difficile tornare purtroppo.

Quindi utilizzare scarsamente gli eventi. Preferisci passare le funzioni ai componenti figlio in modo che i componenti figlio possano avvisare i genitori. Anche questo è un tipo di evento, ma più isolato e più facile da seguire.

Si potrebbe pensare "Beh, che dire di Flux, è tutto sugli eventi?". Ed è sicuro, ma ha una struttura piuttosto rigida per come e quando inviare eventi che lo rendano più facile da gestire.

+0

grazie-- ho fatto ricerche sul flusso. Il flusso è ciò che consiglieresti per gestire la comunicazione degli eventi tra i componenti nidificati? – psvj

+1

Sì, ho notato anche questo durante la creazione della mia applicazione React. Per fortuna l'ho notato presto mentre l'applicazione è ancora infantile ... e mi sono pentito .. rapidamente. La tua analogia con le variabili globali è molto adatta. –

Problemi correlati