React.js How to pass an event through several child components?

I have a response.js application with a structure like this:

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

I want to be able to listen to the onChange event that occurs inside the <-CalcRow-> component, but it is difficult for me to transfer the event down to the root component.

I browsed the web pages and stackoverflow, quite broadly, but did not find examples of how to do this.

What is the best way to pass an event from a deeply nested child component all the way back to the root component so that I can change state?

Here is my complete code:

 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); 
+7
reactjs
source share
3 answers

Just a caution when using pub / sub: it's too easy to go overboard with events. At first, this seems to solve all the problems you have ever had. Then after a while you notice that all of your code is a tangled ball of spaghetti events.

Events are a bit like globals because they tend to do better until they make things worse. And when you find yourself where they make things worse, it's hard to come back unfortunately.

Therefore, use events rarely. Prefer function handoff to child components so that child components can notify parents. This is also a kind of event, but more isolated and easier to follow.

You might think, "Well, what about Flux, is it all about events?" And this is necessary, but it has a rather rigid structure for how and when to send events, which simplifies management.

+4
source share

One solution might be to use the general event manager.

In your parent component you should write

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

and in the subsidiary

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

If you do not want to implement a dispatcher yourself, there are several libraries around. I have not tried, but for example https://github.com/mrdoob/eventdispatcher.js/ seems to do the job.

+1
source share

I use PubSubJS to communicate between my React components ... this way you keep everything independent and loosely coupled.

You can learn more about PubSubJS here: https://github.com/mroderick/PubSubJS

For communication, one component publishes and any subscriber receives data.

I found out about this from this blog: http://maketea.co.uk/2014/03/05/building-robust-web-apps-with-react-part-1.html#component-communication

It uses window.addEventListener , but I do not recommend it, since not all browsers support it, plus PubSubJS is much easier to implement.

+1
source share

All Articles