我有一个react.js应用程序,其结构如下:
<CalcApp /> --- root component, state is set here
<CalcTable /> --- 1st child component
<CalcRow /> --- 2nd child component
- input onChange event
我希望能够听到&lt; -CalcRow-&gt;内发生的onChange事件。组件,但我无法将事件一直传递到根组件。
我已经浏览了网络和stackoverflow,相当广泛,但还没有找到如何执行此操作的示例。
将事件从深层嵌套的子组件一直传递回根组件的最佳方法是什么,以便我可以更改状态?
这是我的完整代码:
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);
答案 0 :(得分:5)
使用pub / sub时要小心谨慎:过于容易过度使用事件。起初,它似乎解决了你曾经遇到的所有问题。过了一会儿,你会注意到你所有的代码都是事件意外的纠结球。
事件有点像全球化,因为他们倾向于让一切变得更好,直到他们让事情变得更糟。当你最终让一切变得更糟时,不幸的是很难回去。
所以稀疏地使用事件。首选将函数传递给子组件,以便子组件可以通知父组件。这也是一种事件,但更加孤立,更容易理解。
你可能会想“那么关于Flux,那是关于什么事件的?”。它确实如此,但对于如何以及何时发送事件具有相当严格的结构,使其更易于管理。
答案 1 :(得分:1)
一种解决方案可以是使用公共事件调度程序。
在您的父组件中,您将编写
var dispatcher = require('./my-dispatcher')
dispatcher.on('my.event', function (e, myArg) {
// do some stuff here
})
和孩子
var dispatcher = require('./my-dispatcher')
dispatcher.trigger('my.event', 'my arg value')
如果您不想自己实施调度程序,可以使用一些库。 我没有尝试过,但是例如https://github.com/mrdoob/eventdispatcher.js/似乎做了这个工作。
答案 2 :(得分:1)
我使用PubSubJS在我的React组件之间进行通信......这样你就可以保持一切彼此独立并松散耦合。
您可以在此处详细了解PubSubJS:https://github.com/mroderick/PubSubJS
要进行通信,一个组件发布,任何订阅者都将获取数据。
我从这个博客中了解到了这一点:http://maketea.co.uk/2014/03/05/building-robust-web-apps-with-react-part-1.html#component-communication
他正在使用window.addEventListener
,但我不推荐它,因为并非所有浏览器都支持它,而且PubSubJS更容易实现。