2015-03-06 18 views
22

Vorrei passare un callback a un componente doppiamente annidato, e mentre sono in grado di passare le proprietà in modo efficace, non riesco a capire come associare il callback al componente corretto in modo che venga attivato. La mia struttura simile a questa:React.js come passare i callback ai componenti figlio?

-OutermostComponent 
    -FirstNestedComponent 
     -SecondNestedComponent 
      -DynamicallyGeneratedListItems 

L'elenco degli elementi quando si fa clic dovrebbe innescare un callback che è il metodo OutermostComponents "onUserInput", ma invece ottengo "errore non rilevato: non definito non è una funzione". Sospetto che il problema riguardi il modo in cui eseguo il rendering di SecondNestedComponent nel primo e passando il callback. Il codice è simile al seguente:

var OutermostComponent = React.createClass({ 
    onUserInput: //my function, 
    render: function() { 
     return (
      <div> 
      //other components 
       <FirstNestedComponent 
        onUserInput={this.onUserInput} 
       /> 
      </div> 
     ); 
    } 
}); 

var FirstNestedComponent = React.createClass({ 
    render: function() { 
     return (
      <div> 
      //other components 
       <SecondNestedComponent 
        onUserInput={this.onUserInput} 
       /> 
      </div> 
     ); 
    } 
}); 
var SecondNestedComponent = React.createClass({ 
    render: function() { 
     var items = []; 
     this.props.someprop.forEach(function(myprop) { 
      items.push(<DynamicallyGeneratedListItems myprop={myprop} onUserInput={this.props.onUserInput}/>);}, this); 
     return (
      <ul> 
       {items} 
      </ul> 
     ); 
    } 
}); 

Come associare correttamente i callback ai componenti nidificati appropriati?

risposta

13

Si sta passando this.onUserInput come una proprietà a FirstNestedComponent. Pertanto, dovresti accedervi in ​​FirstNestedComponent come this.props.onUserInput.

var FirstNestedComponent = React.createClass({ 
    render: function() { 
     return (
      <div> 
       <SecondNestedComponent 
        onUserInput={this.props.onUserInput} 
       /> 
      </div> 
     ); 
    } 
}); 
+0

arn't il concetto di callback contro il paradigma a flusso di dati unidirezionale? – SuperUberDuper

+0

No. Se leggi il tutorial di react, il passaggio dei callback dai componenti principali a quelli secondari è la parte del corso. https://facebook.github.io/react/docs/tutorial.html – gregturn

+2

Nah man. React lega roba "automagicamente" per i metodi passati come "oggetti di scena" ai componenti figlio. Tecnicamente i callback sono ancora conformi alle idee di React ™ del flusso di dati unidirezionale perché il contesto è genitore (non da bambino) – williamle8300

1

Come riferimento, si prega di verificare l'attuazione ho creato a jsfiddle.net/kb3gN/12007

function ListenersService(){ 
    var listeners = {}; 
    this.addListener = function(callback){ 
     var id; 
     if(typeof callback === 'function'){ 
      id = Math.random().toString(36).slice(2); 
      listeners[id] = callback; 
     } 
     return id; 
    } 
    this.removeListener = function(id){ 
     if(listeners[id]){ 
      delete listeners[id]; 
      return true; 
     } 
     return false; 
    } 
    this.notifyListeners = function(data){ 
     for (var id in listeners) { 
      if(listeners.hasOwnProperty(id)){ 
      listeners[id](data); 
      } 
     } 
    } 
} 

function DataService(ListenersService){ 
    var Data = { value: 1 }; 
    var self = this; 

    var listenersService = new ListenersService(); 
    this.addListener = listenersService.addListener; 
    this.removeListener = listenersService.removeListener; 
    this.getData = function(){ 
     return Data; 
    } 

    setInterval(function(){ 
     Data.value++; 
     listenersService.notifyListeners(Data); 
    }, 1000); 
} 
var dataSevice = new DataService(ListenersService); 

var World = React.createClass({ 
    render: function() { 
     return <strong>{this.props.data.value}</strong>; 
    } 
}); 

var Hello = React.createClass({ 
    getInitialState: function() { 
     return { 
      data: this.props.dataService.getData() 
     }; 
    }, 
    componentDidMount: function() { 
     this.props.dataService.addListener(this.updateHandler) 
    }, 
    updateHandler: function(data) { 
     this.setState({ 
      data: data 
     }); 
    }, 
    render: function() { 
     return (
      <div> 
       Value: <World data={this.state.data} /> 
      </div> 
     ); 
    } 
}); 

React.renderComponent(<Hello dataService={dataSevice} />, document.body); 
Problemi correlati