2015-05-24 13 views
7

Mam react.js aplikację ze strukturą tak:React.js Jak przekazywać zdarzenia przez wiele komponentów potomnych?

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

Chcę, aby móc posłuchać zdarzenie onChange dzieje wewnątrz -CalcRow-> Części <, ale mam problemy przechodzącą wydarzenie aż do komponentu głównego.

Rozglądałem się po sieci i stackoverflow, dość szeroko, ale nie znalazłem przykłady, jak to zrobić.

Jaki jest najlepszy sposób przekazania zdarzenia z głęboko zagnieżdżonego komponentu potomnego z powrotem do komponentu głównego, aby można było zmienić stan?

Oto mój pełny kod:

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

Odpowiedz

1

Jednym z rozwiązań może być wykorzystanie wspólnego dyspozytora zdarzeń.

W komponentu macierzystego, byś napisać

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

i dziecka

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

Jeśli nie chcą wprowadzić dyspozytora samodzielnie, istnieją pewne biblioteki dookoła. Nie próbowałem go, ale na przykład https://github.com/mrdoob/eventdispatcher.js/ wydaje się wykonywać tę pracę.

+0

dziękuję patrzę na to – psvj

+0

Istnieje szersza informacja na ten temat na stronie internetowej Facebook strumienia. https: //facebook.github.io/flux/docs/dispatcher.html –

+0

Jeśli ktoś w podobnej sytuacji czyta to, skończyło się na implementacji architektury strumienia przy użyciu refluksu, ponieważ wydawało się, że jest to najprostsza implementacja strumienia. – psvj

1

Używam PubSubJS do komunikowania się między moimi komponentami React ... w ten sposób zachowujesz wszystko niezależnie od siebie i luźno sprzężone.

Możesz przeczytać więcej o PubSubJS tutaj: https://github.com/mroderick/PubSubJS

Aby komunikować, jeden składnik publikowania i każdy abonent otrzyma dane.

Dowiedziałem się o tym z tego bloga: http://maketea.co.uk/2014/03/05/building-robust-web-apps-with-react-part-1.html#component-communication

On używa window.addEventListener ale nie polecam go, ponieważ nie wszystkie przeglądarka je obsługuje, plus PubSubJS jest znacznie łatwiejsze do wdrożenia.

4

Tylko słowa ostrożności podczas korzystania z pub/sub: zbyt łatwo jest wyjść za burtę z wydarzeniami. Na początku wydaje się, że rozwiązuje wszystkie problemy, jakie kiedykolwiek miałeś. Potem po chwili zauważysz, że cały twój kod jest splątaną piłką event-spaghetti.

Wydarzenia są trochę jak globale, ponieważ mają tendencję do czynienia wszystkiego lepiej, dopóki wszystko nie pogorszy. A kiedy skończysz, gdzie wszystko pogorszysz, ciężko wrócić niestety.

Wykorzystaj więc zdarzenia rzadziej. Wolimy przekazywać funkcje do komponentów potomnych, aby komponenty potomne mogły powiadamiać rodziców. To także jest wydarzeniem, ale bardziej odizolowanym i łatwiejszym do naśladowania.

Możesz pomyśleć: "A co z Flux, to wszystko o wydarzeniach?". I to na pewno, ale ma dość sztywną strukturę, jak i kiedy wysyłać zdarzenia, co ułatwia zarządzanie.

+0

dzięki - badałem topnik. Czy strumień jest polecany do obsługi komunikacji zdarzeń między komponentami zagnieżdżonymi? – psvj

+1

Yup Zauważyłem to również podczas budowania aplikacji React. Na szczęście zauważyłem to wcześnie, podczas gdy aplikacja jest nadal niemowlęta ... i żałowałem .. szybko. Twoja analogia do zmiennych globalnych jest bardzo odpowiednia. –

Powiązane problemy