React.js как передать обратные вызовы дочерним компонентам?
Я хотел бы передать обратный вызов дважды вложенному компоненту, и, хотя я могу эффективно передавать свойства, я не могу понять, как связать обратный вызов с правильным компонентом, чтобы он срабатывал. Моя структура выглядит так:
-OutermostComponent
-FirstNestedComponent
-SecondNestedComponent
-DynamicallyGeneratedListItems
Элементы списка при нажатии должны вызывать обратный вызов, который является методом OutermostComponents "onUserInput", но вместо этого я получаю сообщение "Uncaught Error: Undefined не является функцией". Я подозреваю, что проблема заключается в том, как я передаю SecondNestedComponent внутри первого и передавая ему обратный вызов. Код выглядит примерно так:
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>
);
}
});
Как правильно привязывать обратные вызовы к соответствующим вложенным компонентам?
Ответы
Ответ 1
Вы передаете this.onUserInput
как свойство FirstNestedComponent
. Поэтому вы должны получить доступ к нему в FirstNestedComponent
как this.props.onUserInput
.
var FirstNestedComponent = React.createClass({
render: function() {
return (
<div>
<SecondNestedComponent
onUserInput={this.props.onUserInput}
/>
</div>
);
}
});
Ответ 2
Для справки, пожалуйста, проверьте реализацию, которую я создал в 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);