Pass props to parent component in React.js - javascript
Is there not a simple way to pass a child's props to its parent using events, in React.js?
var Child = React.createClass({
render: function() {
<a onClick={this.props.onClick}>Click me</a>
}
});
var Parent = React.createClass({
onClick: function(event) {
// event.component.props ?why is this not available?
},
render: function() {
<Child onClick={this.onClick} />
}
});
I know you can use controlled components to pass an input's value but it'd be nice to pass the whole kit n' kaboodle. Sometimes the child component contains a set of information you'd rather not have to look up.
Perhaps there's a way to bind the component to the event?
UPDATE – 9/1/2015
After using React for over a year, and spurred on by Sebastien Lorber's answer, I've concluded passing child components as arguments to functions in parents is not in fact the React way, nor was it ever a good idea. I've switched the answer.
Edit: see the end examples for ES6 updated examples.
This answer simply handle the case of direct parent-child relationship. When parent and child have potentially a lot of intermediaries, check this answer.
Other solutions are missing the point
While they still work fine, other answers are missing something very important.
Is there not a simple way to pass a child's props to its parent using events, in React.js?
The parent already has that child prop!: if the child has a prop, then it is because its parent provided that prop to the child! Why do you want the child to pass back the prop to the parent, while the parent obviously already has that prop?
Better implementation
Child: it really does not have to be more complicated than that.
var Child = React.createClass({
render: function () {
return <button onClick={this.props.onClick}>{this.props.text}</button>;
},
});
Parent with single child: using the value it passes to the child
var Parent = React.createClass({
getInitialState: function() {
return {childText: "Click me! (parent prop)"};
},
render: function () {
return (
<Child onClick={this.handleChildClick} text={this.state.childText}/>
);
},
handleChildClick: function(event) {
// You can access the prop you pass to the children
// because you already have it!
// Here you have it in state but it could also be
// in props, coming from another parent.
alert("The Child button text is: " + this.state.childText);
// You can also access the target of the click here
// if you want to do some magic stuff
alert("The Child HTML is: " + event.target.outerHTML);
}
});
JsFiddle
Parent with list of children: you still have everything you need on the parent and don't need to make the child more complicated.
var Parent = React.createClass({
getInitialState: function() {
return {childrenData: [
{childText: "Click me 1!", childNumber: 1},
{childText: "Click me 2!", childNumber: 2}
]};
},
render: function () {
var children = this.state.childrenData.map(function(childData,childIndex) {
return <Child onClick={this.handleChildClick.bind(null,childData)} text={childData.childText}/>;
}.bind(this));
return <div>{children}</div>;
},
handleChildClick: function(childData,event) {
alert("The Child button data is: " + childData.childText + " - " + childData.childNumber);
alert("The Child HTML is: " + event.target.outerHTML);
}
});
JsFiddle
It is also possible to use this.handleChildClick.bind(null,childIndex) and then use this.state.childrenData[childIndex]
Note we are binding with a null context because otherwise React issues a warning related to its autobinding system. Using null means you don't want to change the function context. See also.
About encapsulation and coupling in other answers
This is for me a bad idea in term of coupling and encapsulation:
var Parent = React.createClass({
handleClick: function(childComponent) {
// using childComponent.props
// using childComponent.refs.button
// or anything else using childComponent
},
render: function() {
<Child onClick={this.handleClick} />
}
});
Using props:
As I explained above, you already have the props in the parent so it's useless to pass the whole child component to access props.
Using refs:
You already have the click target in the event, and in most case this is enough.
Additionnally, you could have used a ref directly on the child:
<Child ref="theChild" .../>
And access the DOM node in the parent with
React.findDOMNode(this.refs.theChild)
For more advanced cases where you want to access multiple refs of the child in the parent, the child could pass all the dom nodes directly in the callback.
The component has an interface (props) and the parent should not assume anything about the inner working of the child, including its inner DOM structure or which DOM nodes it declares refs for. A parent using a ref of a child means that you tightly couple the 2 components.
To illustrate the issue, I'll take this quote about the Shadow DOM, that is used inside browsers to render things like sliders, scrollbars, video players...:
They created a boundary between what you, the Web developer can reach
and what’s considered implementation details, thus inaccessible to
you. The browser however, can traipse across this boundary at will.
With this boundary in place, they were able to build all HTML elements
using the same good-old Web technologies, out of the divs and spans
just like you would.
The problem is that if you let the child implementation details leak into the parent, you make it very hard to refactor the child without affecting the parent. This means as a library author (or as a browser editor with Shadow DOM) this is very dangerous because you let the client access too much, making it very hard to upgrade code without breaking retrocompatibility.
If Chrome had implemented its scrollbar letting the client access the inner dom nodes of that scrollbar, this means that the client may have the possibility to simply break that scrollbar, and that apps would break more easily when Chrome perform its auto-update after refactoring the scrollbar... Instead, they only give access to some safe things like customizing some parts of the scrollbar with CSS.
About using anything else
Passing the whole component in the callback is dangerous and may lead novice developers to do very weird things like calling childComponent.setState(...) or childComponent.forceUpdate(), or assigning it new variables, inside the parent, making the whole app much harder to reason about.
Edit: ES6 examples
As many people now use ES6, here are the same examples for ES6 syntax
The child can be very simple:
const Child = ({
onClick,
text
}) => (
<button onClick={onClick}>
{text}
</button>
)
The parent can be either a class (and it can eventually manage the state itself, but I'm passing it as props here:
class Parent1 extends React.Component {
handleChildClick(childData,event) {
alert("The Child button data is: " + childData.childText + " - " + childData.childNumber);
alert("The Child HTML is: " + event.target.outerHTML);
}
render() {
return (
<div>
{this.props.childrenData.map(child => (
<Child
key={child.childNumber}
text={child.childText}
onClick={e => this.handleChildClick(child,e)}
/>
))}
</div>
);
}
}
But it can also be simplified if it does not need to manage state:
const Parent2 = ({childrenData}) => (
<div>
{childrenData.map(child => (
<Child
key={child.childNumber}
text={child.childText}
onClick={e => {
alert("The Child button data is: " + child.childText + " - " + child.childNumber);
alert("The Child HTML is: " + e.target.outerHTML);
}}
/>
))}
</div>
)
JsFiddle
PERF WARNING (apply to ES5/ES6): if you are using PureComponent or shouldComponentUpdate, the above implementations will not be optimized by default because using onClick={e => doSomething()}, or binding directly during the render phase, because it will create a new function everytime the parent renders. If this is a perf bottleneck in your app, you can pass the data to the children, and reinject it inside "stable" callback (set on the parent class, and binded to this in class constructor) so that PureComponent optimization can kick in, or you can implement your own shouldComponentUpdate and ignore the callback in the props comparison check.
You can also use Recompose library, which provide higher order components to achieve fine-tuned optimisations:
// A component that is expensive to render
const ExpensiveComponent = ({ propA, propB }) => {...}
// Optimized version of same component, using shallow comparison of props
// Same effect as React's PureRenderMixin
const OptimizedComponent = pure(ExpensiveComponent)
// Even more optimized: only updates if specific prop keys have changed
const HyperOptimizedComponent = onlyUpdateForKeys(['propA', 'propB'])(ExpensiveComponent)
In this case you could optimize the Child component by using:
const OptimizedChild = onlyUpdateForKeys(['text'])(Child)
Update (9/1/15): The OP has made this question a bit of a moving target. It’s been updated again. So, I feel responsible to update my reply.
First, an answer to your provided example:
Yes, this is possible.
You can solve this by updating Child’s onClick to be this.props.onClick.bind(null, this):
var Child = React.createClass({
render: function () {
return <a onClick={this.props.onClick.bind(null, this)}>Click me</a>;
}
});
The event handler in your Parent can then access the component and event like so:
onClick: function (component, event) {
// console.log(component, event);
},
JSBin snapshot
But the question itself is misleading
Parent already knows Child’s props.
This isn’t clear in the provided example because no props are actually being provided. This sample code might better support the question being asked:
var Child = React.createClass({
render: function () {
return <a onClick={this.props.onClick}> {this.props.text} </a>;
}
});
var Parent = React.createClass({
getInitialState: function () {
return { text: "Click here" };
},
onClick: function (event) {
// event.component.props ?why is this not available?
},
render: function() {
return <Child onClick={this.onClick} text={this.state.text} />;
}
});
It becomes much clearer in this example that you already know what the props of Child are.
JSBin snapshot
If it’s truly about using a Child’s props…
If it’s truly about using a Child’s props, you can avoid any hookup with Child altogether.
JSX has a spread attributes API I often use on components like Child. It takes all the props and applies them to a component. Child would look like this:
var Child = React.createClass({
render: function () {
return <a {...this.props}> {this.props.text} </a>;
}
});
Allowing you to use the values directly in the Parent:
var Parent = React.createClass({
getInitialState: function () {
return { text: "Click here" };
},
onClick: function (text) {
alert(text);
},
render: function() {
return <Child onClick={this.onClick.bind(null, this.state.text)} text={this.state.text} />;
}
});
JSBin snapshot
And there's no additional configuration required as you hookup additional Child components
var Parent = React.createClass({
getInitialState: function () {
return {
text: "Click here",
text2: "No, Click here",
};
},
onClick: function (text) {
alert(text);
},
render: function() {
return <div>
<Child onClick={this.onClick.bind(null, this.state.text)} text={this.state.text} />
<Child onClick={this.onClick.bind(null, this.state.text2)} text={this.state.text2} />
</div>;
}
});
JSBin snapshot
But I suspect that’s not your actual use case. So let’s dig further…
A robust practical example
The generic nature of the provided example is a hard to talk about. I’ve created a component that demonstrations a practical use for the question above, implemented in a very Reacty way:
DTServiceCalculator working example
DTServiceCalculator repo
This component is a simple service calculator. You provide it with a list of services (with names and prices) and it will calculate a total the selected prices.
Children are blissfully ignorant
ServiceItem is the child-component in this example. It doesn’t have many opinions about the outside world. It requires a few props, one of which is a function to be called when clicked.
<div onClick={this.props.handleClick.bind(this.props.index)} />
It does nothing but to call the provided handleClick callback with the provided index[source].
Parents are Children
DTServicesCalculator is the parent-component is this example. It’s also a child. Let’s look.
DTServiceCalculator creates a list of child-component (ServiceItems) and provides them with props [source]. It’s the parent-component of ServiceItem but it`s the child-component of the component passing it the list. It doesn't own the data. So it again delegates handling of the component to its parent-component source
<ServiceItem chosen={chosen} index={i} key={id} price={price} name={name} onSelect={this.props.handleServiceItem} />
handleServiceItem captures the index, passed from the child, and provides it to its parent [source]
handleServiceClick (index) {
this.props.onSelect(index);
}
Owners know everything
The concept of “Ownership” is an important one in React. I recommend reading more about it here.
In the example I’ve shown, I keep delegating handling of an event up the component tree until we get to the component that owns the state.
When we finally get there, we handle the state selection/deselection like so [source]:
handleSelect (index) {
let services = […this.state.services];
services[index].chosen = (services[index].chosen) ? false : true;
this.setState({ services: services });
}
Conclusion
Try keeping your outer-most components as opaque as possible. Strive to make sure that they have very few preferences about how a parent-component might choose to implement them.
Keep aware of who owns the data you are manipulating. In most cases, you will need to delegate event handling up the tree to the component that owns that state.
Aside: The Flux pattern is a good way to reduce this type of necessary hookup in apps.
It appears there's a simple answer. Consider this:
var Child = React.createClass({
render: function() {
<a onClick={this.props.onClick.bind(null, this)}>Click me</a>
}
});
var Parent = React.createClass({
onClick: function(component, event) {
component.props // #=> {Object...}
},
render: function() {
<Child onClick={this.onClick} />
}
});
The key is calling bind(null, this) on the this.props.onClick event, passed from the parent. Now, the onClick function accepts arguments component, AND event. I think that's the best of all worlds.
UPDATE: 9/1/2015
This was a bad idea: letting child implementation details leak in to the parent was never a good path. See Sebastien Lorber's answer.
The question is how to pass argument from child to parent component. This example is easy to use and tested:
//Child component
class Child extends React.Component {
render() {
var handleToUpdate = this.props.handleToUpdate;
return (<div><button onClick={() => handleToUpdate('someVar')}>Push me</button></div>
)
}
}
//Parent component
class Parent extends React.Component {
constructor(props) {
super(props);
var handleToUpdate = this.handleToUpdate.bind(this);
}
handleToUpdate(someArg){
alert('We pass argument from Child to Parent: \n' + someArg);
}
render() {
var handleToUpdate = this.handleToUpdate;
return (<div>
<Child handleToUpdate = {handleToUpdate.bind(this)} />
</div>)
}
}
if(document.querySelector("#demo")){
ReactDOM.render(
<Parent />,
document.querySelector("#demo")
);
}
Look at JSFIDDLE
Basically you use props to send information to and from Child and Parent.
Adding to all the wonderful answers, let me give a simple example that explains passing values from child to parent component in React
App.js
class App extends React.Component {
constructor(){
super();
this.handleFilterUpdate = this.handleFilterUpdate.bind(this);
this.state={name:'igi'}
}
handleFilterUpdate(filterValue) {
this.setState({
name: filterValue
});
}
render() {
return (
<div>
<Header change={this.handleFilterUpdate} name={this.state.name} />
<p>{this.state.name}</p>
</div>
);
}
}
Header.js
class Header extends React.Component {
constructor(){
super();
this.state={
names: 'jessy'
}
}
Change(event) {
// this.props.change(this.state.names);
this.props.change('jessy');
}
render() {
return (
<button onClick={this.Change.bind(this)}>click</button>
);
}
}
Main.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';
ReactDOM.render(<App />, document.getElementById('app'));
Thats it , now you can pass values from your client to the server.
Take a look at the Change function in the Header.js
Change(event) {
// this.props.change(this.state.names);
this.props.change('jessy');
}
This is how you push values into the props from client to the server
Here is a simple 3 step ES6 implementation using function binding in the parent constructor. This is the first way the official react tutorial recommends (there is also public class fields syntax not covered here). You can find all of this information here https://reactjs.org/docs/handling-events.html
Binding Parent Functions so Children Can Call Them (And pass data up to the parent! :D )
Make sure in the parent constructor you bind the function you created in the parent
Pass the bound function down to the child as a prop (No lambda because we are passing a ref to function)
Call the bound function from a child event (Lambda! We're calling the function when the event is fired.
If we don't do this the function will automatically run on load and not be triggered on the event.)
Parent Function
handleFilterApply(filterVals){}
Parent Constructor
this.handleFilterApply = this.handleFilterApply.bind(this);
Prop Passed to Child
onApplyClick = {this.handleFilterApply}
Child Event Call
onClick = {() => {props.onApplyClick(filterVals)}
This is an example without using the onClick event. I simply pass a callback function to the child by props. With that callback the child call also send data back. I was inspired by the examples in the docs.
Small example (this is in a tsx files, so props and states must be declared fully, I deleted some logic out of the components, so it is less code).
*Update: Important is to bind this to the callback, otherwise the callback has the scope of the child and not the parent. Only problem: it is the "old" parent...
SymptomChoser is the parent:
interface SymptomChooserState {
// true when a symptom was pressed can now add more detail
isInDetailMode: boolean
// since when user has this symptoms
sinceDate: Date,
}
class SymptomChooser extends Component<{}, SymptomChooserState> {
state = {
isInDetailMode: false,
sinceDate: new Date()
}
helloParent(symptom: Symptom) {
console.log("This is parent of: ", symptom.props.name);
// TODO enable detail mode
}
render() {
return (
<View>
<Symptom name='Fieber' callback={this.helloParent.bind(this)} />
</View>
);
}
}
Symptom is the child (in the props of the child I declared the callback function, in the function selectedSymptom the callback is called):
interface SymptomProps {
// name of the symptom
name: string,
// callback to notify SymptomChooser about selected Symptom.
callback: (symptom: Symptom) => void
}
class Symptom extends Component<SymptomProps, SymptomState>{
state = {
isSelected: false,
severity: 0
}
selectedSymptom() {
this.setState({ isSelected: true });
this.props.callback(this);
}
render() {
return (
// symptom is not selected
<Button
style={[AppStyle.button]}
onPress={this.selectedSymptom.bind(this)}>
<Text style={[AppStyle.textButton]}>{this.props.name}</Text>
</Button>
);
}
}
Related
How to read child elements from a React component
I want to get a list of all child elements of a react component. For example: Parent.js <Parent> <SomeComponent/> </Parent> SomeComponent.js <SomeComponent> <ChildElement1/> <ClhidElement2/> </SomeComponent> So in Parent.js I want to get ChildElement1 and ChildElement2. Is that possible? My Use case is: I'm passing form fields (Field component) to a generic Form component. The Form element receives an object of default values and also other things (what CRUD/resource it is related to for example). And it must inject these values in the Fields. Instead of passing all fields one by one and avoid repetion I created containers like "UserFields" and a few others and they are the ones that have the Fields components. So I need Form to read the Fields in UserFields. But since the fields are already inside UserFields, I can't figure out how to get them.
React is designed to be unidirectional data flow and following Flux architecture, and hence to keep best practices, it's always top down (from parent to child, not bidirectional). However, you can achieve them in several options such as implementing React with redux or React Context
I am considering that your child components are mapped from array inside <SomeComponent /> Try this inside your parent state = { child: [] } renderChildren = () => { if(this.state.child.length > 0) { return this.state.child.map(e => { return ( <div>{e}</div> ) }) } } returnChild = (data) => { var child = []; for(var i = 0; i < data.length; i++) { child.push(data[i]) } this.setState(prevState => ({child: [...prevState.child, child]})); } return ( <div> <SomeComponent returnChild={(child) => this.returnChild(child)} /> {this.renderChildren()} </div> ) Add this method to your <SomeComponent /> component like this along with other code. onGettingMoreChild = (child) => { this.props.returnChild(child) } Don't forget to call onGettingMoreChild whenever there is a new child created. I have not tested this code. Please playaround with it if needed. Also, remember to pass in your entire view as child to the method onGettingMoreChild Example of child variable passed to onGettingMoreChild is <div>I am child one!!</div>
Pass argument onClick to props.function() executed via refs
I'm sorry this title might be a bit of a head-scratcher, I just can't quite think of how exactly to phrase my issue (open to any suggestions). Basically there are 3 components: parent, ChildA, and ChildB Parent renders both children, ChildB has a ref tag, Parent uses that ref tag to pass ChildB's function to ChildA. class Parent extends Component { render() { <ChildA openChildB={() => this.childb.open()} /> <ChildB ref={instance => { this.childb = instance; }} /> } } Pretty basic. The issue I am running into is that when ChildA executes that function it needs to pass an argument. I can't seem to figure out the correct way to do that. I tried using a different syntax to pass the function down to ChildA - <ChildA openChildB={this.childb.open} /> but that results in an error, Can't Read Property Of Undefined. How can I pass a variable through this function? Any help would be very appreciated! Edit: I know I could pass the argument up to Parent and then from there place it in the function () => this.childb.open(arg) but for the sake of organization I would really prefer to handle that all within ChildA.
You can use the following: class Parent extends Component { render() { <ChildA openChildB={(arg1) => this.childb.open(arg1)} /> <ChildB ref={instance => { this.childb = instance; }} /> } } And inside ChildA you should make sure to pass the relevant argument when you call the this.props.openChildB: function handleOpenOnB() { // This is an example, you should use the relevant value you want to pass to the openChildB function this.props.openChildB(this.state.val); }
How to access one component's state from another component
How do I access one component's state in another component? Below is my code and I'm trying to access the state of component a in component b. var a = React.createClass({ getInitialState: function () { return { first: "1" }; }, render: function () { // Render HTML here. } }); var b = React.createClass({ getInitialState: function () { return { second: a.state.first }; }, render: function () { // Render HTML here. } }); But I'm not getting anything.
Even if you try doing this way, it is not correct method to access the state. Better to have a parent component whose children are a and b. The ParentComponent will maintain the state and pass it as props to the children. For instance, var ParentComponent = React.createClass({ getInitialState : function() { return { first: 1, } } changeFirst: function(newValue) { this.setState({ first: newValue, }); } render: function() { return ( <a first={this.state.first} changeFirst={this.changeFirst.bind(this)} /> <b first={this.state.first} changeFirst={this.changeFirst.bind(this)} /> ) } } Now in your child compoenents a and b, access first variable using this.props.first. When you wish to change the value of first call this.props.changeFirst() function of the ParentComponent. This will change the value and will be thus reflected in both the children a and b. I am writing component a here, b will be similar: var a = React.createClass({ render: function() { var first = this.props.first; // access first anywhere using this.props.first in child // render JSX } }
If two components need access to the same state they should have a common ancestor where the state is kept. So component A is the parent of B and C. Component A has the state, and passes it down as props to B and C. If you want to change the state from B you pass down a callback function as a prop.
I would suggest you use a state manager like Redux (personal favorite), MobX reflux, etc to manage your state. How these works is they allow you to contain all shared state in one state storage (called a store), and whatever component needs access to a part of that shared state, it will just get it from the store. It looked very hard to get started with but once you get over the small challenges, get 2 or 3 "wtf's" out of the way. It gets easier. Take a look here: http://redux.js.org/ EDIT: Redux is good but the boilerplate code is really a turn off... for those of you looking for a simpler, more magical (this can be good and bad) solution use mobx : https://mobx.js.org/
in the child component create function that sets the state: changeTheState(){ this.setState({something:"some value"}) } and in parent component give the child a ref as following: <Child ref={component => this._child = component}/> then in parent make a function to access the changeTheState() parentFunction(){ this._child.changeTheState(); } and just use the parentFunction.
If you have A and B component where B is a child of A, you can pass a function to change the state of A though props to B. function B(props) { return <button onClick={props.changeA} /> } class A extends React.Component { //constructor //pass this function to B to change A's state handleA() { this.setState({}); } render() { return <B changeA={() => this.handleA()} /> } }
Take a look at React Context Context provides a way to pass data through the component tree without having to pass props down manually at every level. You can also update Context from a nested component if required.
ReactJS bind a component method the correct way
I am trying to use .bind() when using a method in my component. The reason is simple: In a loop I am returing Components and extend them with a property which is calling a method. But for every loop-item this I want to extend the this Object with some information (like a key). Example: Items.jsx Items = React.createClass({ eventMethod() { console.log('this event was triggered by key:', this.key); }, items() { let items = []; let properties = {}; _.each(this.props.items, (itemData, key)=>{ properties.eventMethodInItem = this.eventMethod.bind(_.extend(this, { key })); let {...props} = properties; let item = <Item {...props} key={key} />; items.push(item); }); return items; }, render() { return(<div>{this.items()}</div>); } }); Item.jsx Item = React.createClass(...); In this case (and its working) when the Item Component is triggering the prop "eventMethodInItem" my method "eventMethod" will be called and this.key has the correct value! So - whats now the question ? Its working perfect, right ? Yes. But ReactJS does not want me to do this. This is what ReactJS is telling me as a console log. Warning: bind(): You are binding a component method to the component. React does this for you automatically in a high-performance way, so you can safely remove this call. See Items Maybe you think its a "bad" way to add children to the component like I am doing it but in my special case I need to do this in this way - so I need to bind new information to a method.
I'm not going to pretend that I understand what you are trying to do here, but maybe I can help clear it up anyway. React takes all of the top level methods found on each component and automagically binds them to the context of the component. This prevents other methods from overriding the context of this and as a result, if you try to rebind the method, React says "Hey don't bother. I already got it" — which is the warning you are seeing. Assuming that you really want do this (each time you are mutating the outer properties object by overriding the eventMethodInItem property). properties.eventMethodInItem = this.eventMethod.bind(_.extend(this, { key })); Then I can't see any reason that the eventMethod has to live on the component, rather than just in the scope of the items function. items() { const eventMethod = function() { console.log('this event was triggered by key:', this.key); } // ... _.each(this.props.items, (itemData, key)=>{ properties.eventMethodInItem = eventMethod.bind(_.extend(this, { key })); // ... }); }, That way you don't have to fight React to get your program to work.
React is already autobinding this when using React.createClass http://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#under-the-hood-autobinding-and-event-delegation Change your binding to properties.eventMethodInItem = this.eventMethod.bind(null,key); and your eventMethod to eventMethod(key) { console.log('this event was triggered by key:', key); } I also suggest using _.map instead of _.each items() { return _.map(this.props.items, (itemData, key) => { return <Item handleEventMethod={this.eventMethod.bind(null,key)} key={key} />; }); },
Good pattern https://www.newmediacampaigns.com/blog/refactoring-react-components-to-es6-classes Before : class ExampleComponent extends React.Component { constructor() { super(); this. _handleClick = this. _handleClick.bind(this); this. _handleFoo = this. _handleFoo.bind(this); } // ... } After : class BaseComponent extends React.Component { _bind(...methods) { methods.forEach( (method) => this[method] = this[method].bind(this) ); } } class ExampleComponent extends BaseComponent { constructor() { super(); this._bind('_handleClick', '_handleFoo'); } // ... } another good hacks for this topic http://egorsmirnov.me/2015/08/16/react-and-es6-part3.html
How can I communicate between related react components?
I just got started with ReactJS and am a little stuck on a problem that I have. My application is essentially a list with filters and a button to change the layout. At the moment I'm using three components: <list />, < Filters /> and <TopBar />, now obviously when I change settings in < Filters /> I want to trigger some method in <list /> to update my view. How can I make those 3 components interact with each other, or do I need some sort of global data model where I can just make changes to?
The best approach would depend on how you plan to arrange those components. A few example scenarios that come to mind right now: <Filters /> is a child component of <List /> Both <Filters /> and <List /> are children of a parent component <Filters /> and <List /> live in separate root components entirely. There may be other scenarios that I'm not thinking of. If yours doesn't fit within these, then let me know. Here are some very rough examples of how I've been handling the first two scenarios: Scenario #1 You could pass a handler from <List /> to <Filters />, which could then be called on the onChange event to filter the list with the current value. JSFiddle for #1 → /** #jsx React.DOM */ var Filters = React.createClass({ handleFilterChange: function() { var value = this.refs.filterInput.getDOMNode().value; this.props.updateFilter(value); }, render: function() { return <input type="text" ref="filterInput" onChange={this.handleFilterChange} placeholder="Filter" />; } }); var List = React.createClass({ getInitialState: function() { return { listItems: ['Chicago', 'New York', 'Tokyo', 'London', 'San Francisco', 'Amsterdam', 'Hong Kong'], nameFilter: '' }; }, handleFilterUpdate: function(filterValue) { this.setState({ nameFilter: filterValue }); }, render: function() { var displayedItems = this.state.listItems.filter(function(item) { var match = item.toLowerCase().indexOf(this.state.nameFilter.toLowerCase()); return (match !== -1); }.bind(this)); var content; if (displayedItems.length > 0) { var items = displayedItems.map(function(item) { return <li>{item}</li>; }); content = <ul>{items}</ul> } else { content = <p>No items matching this filter</p>; } return ( <div> <Filters updateFilter={this.handleFilterUpdate} /> <h4>Results</h4> {content} </div> ); } }); React.renderComponent(<List />, document.body); Scenario #2 Similar to scenario #1, but the parent component will be the one passing down the handler function to <Filters />, and will pass the filtered list to <List />. I like this method better since it decouples the <List /> from the <Filters />. JSFiddle for #2 → /** #jsx React.DOM */ var Filters = React.createClass({ handleFilterChange: function() { var value = this.refs.filterInput.getDOMNode().value; this.props.updateFilter(value); }, render: function() { return <input type="text" ref="filterInput" onChange={this.handleFilterChange} placeholder="Filter" />; } }); var List = React.createClass({ render: function() { var content; if (this.props.items.length > 0) { var items = this.props.items.map(function(item) { return <li>{item}</li>; }); content = <ul>{items}</ul> } else { content = <p>No items matching this filter</p>; } return ( <div className="results"> <h4>Results</h4> {content} </div> ); } }); var ListContainer = React.createClass({ getInitialState: function() { return { listItems: ['Chicago', 'New York', 'Tokyo', 'London', 'San Francisco', 'Amsterdam', 'Hong Kong'], nameFilter: '' }; }, handleFilterUpdate: function(filterValue) { this.setState({ nameFilter: filterValue }); }, render: function() { var displayedItems = this.state.listItems.filter(function(item) { var match = item.toLowerCase().indexOf(this.state.nameFilter.toLowerCase()); return (match !== -1); }.bind(this)); return ( <div> <Filters updateFilter={this.handleFilterUpdate} /> <List items={displayedItems} /> </div> ); } }); React.renderComponent(<ListContainer />, document.body); Scenario #3 When the components can't communicate between any sort of parent-child relationship, the documentation recommends setting up a global event system.
There are multiple ways to make components communicate. Some can be suited to your usecase. Here is a list of some I've found useful to know. React Parent / Child direct communication const Child = ({fromChildToParentCallback}) => ( <div onClick={() => fromChildToParentCallback(42)}> Click me </div> ); class Parent extends React.Component { receiveChildValue = (value) => { console.log("Parent received value from child: " + value); // value is 42 }; render() { return ( <Child fromChildToParentCallback={this.receiveChildValue}/> ) } } Here the child component will call a callback provided by the parent with a value, and the parent will be able to get the value provided by the children in the parent. If you build a feature/page of your app, it's better to have a single parent managing the callbacks/state (also called container or smart component), and all childs to be stateless, only reporting things to the parent. This way you can easily "share" the state of the parent to any child that need it. Context React Context permits to hold state at the root of your component hierarchy, and be able to inject this state easily into very deeply nested components, without the hassle to have to pass down props to every intermediate components. Until now, context was an experimental feature, but a new API is available in React 16.3. const AppContext = React.createContext(null) class App extends React.Component { render() { return ( <AppContext.Provider value={{language: "en",userId: 42}}> <div> ... <SomeDeeplyNestedComponent/> ... </div> </AppContext.Provider> ) } }; const SomeDeeplyNestedComponent = () => ( <AppContext.Consumer> {({language}) => <div>App language is currently {language}</div>} </AppContext.Consumer> ); The consumer is using the render prop / children function pattern Check this blog post for more details. Before React 16.3, I'd recommend using react-broadcast which offer quite similar API, and use former context API. Portals Use a portal when you'd like to keep 2 components close together to make them communicate with simple functions, like in normal parent / child, but you don't want these 2 components to have a parent/child relationship in the DOM, because of visual / CSS constraints it implies (like z-index, opacity...). In this case you can use a "portal". There are different react libraries using portals, usually used for modals, popups, tooltips... Consider the following: <div className="a"> a content <Portal target="body"> <div className="b"> b content </div> </Portal> </div> Could produce the following DOM when rendered inside reactAppContainer: <body> <div id="reactAppContainer"> <div className="a"> a content </div> </div> <div className="b"> b content </div> </body> More details here Slots You define a slot somewhere, and then you fill the slot from another place of your render tree. import { Slot, Fill } from 'react-slot-fill'; const Toolbar = (props) => <div> <Slot name="ToolbarContent" /> </div> export default Toolbar; export const FillToolbar = ({children}) => <Fill name="ToolbarContent"> {children} </Fill> This is a bit similar to portals except the filled content will be rendered in a slot you define, while portals generally render a new dom node (often a children of document.body) Check react-slot-fill library Event bus As stated in the React documentation: For communication between two components that don't have a parent-child relationship, you can set up your own global event system. Subscribe to events in componentDidMount(), unsubscribe in componentWillUnmount(), and call setState() when you receive an event. There are many things you can use to setup an event bus. You can just create an array of listeners, and on event publish, all listeners would receive the event. Or you can use something like EventEmitter or PostalJs Flux Flux is basically an event bus, except the event receivers are stores. This is similar to the basic event bus system except the state is managed outside of React Original Flux implementation looks like an attempt to do Event-sourcing in a hacky way. Redux is for me the Flux implementation that is the closest from event-sourcing, an benefits many of event-sourcing advantages like the ability to time-travel. It is not strictly linked to React and can also be used with other functional view libraries. Egghead's Redux video tutorial is really nice and explains how it works internally (it really is simple). Cursors Cursors are coming from ClojureScript/Om and widely used in React projects. They permit to manage the state outside of React, and let multiple components have read/write access to the same part of the state, without needing to know anything about the component tree. Many implementations exists, including ImmutableJS, React-cursors and Omniscient Edit 2016: it seems that people agree cursors work fine for smaller apps but it does not scale well on complex apps. Om Next does not have cursors anymore (while it's Om that introduced the concept initially) Elm architecture The Elm architecture is an architecture proposed to be used by the Elm language. Even if Elm is not ReactJS, the Elm architecture can be done in React as well. Dan Abramov, the author of Redux, did an implementation of the Elm architecture using React. Both Redux and Elm are really great and tend to empower event-sourcing concepts on the frontend, both allowing time-travel debugging, undo/redo, replay... The main difference between Redux and Elm is that Elm tend to be a lot more strict about state management. In Elm you can't have local component state or mount/unmount hooks and all DOM changes must be triggered by global state changes. Elm architecture propose a scalable approach that permits to handle ALL the state inside a single immutable object, while Redux propose an approach that invites you to handle MOST of the state in a single immutable object. While the conceptual model of Elm is very elegant and the architecture permits to scale well on large apps, it can in practice be difficult or involve more boilerplate to achieve simple tasks like giving focus to an input after mounting it, or integrating with an existing library with an imperative interface (ie JQuery plugin). Related issue. Also, Elm architecture involves more code boilerplate. It's not that verbose or complicated to write but I think the Elm architecture is more suited to statically typed languages. FRP Libraries like RxJS, BaconJS or Kefir can be used to produce FRP streams to handle communication between components. You can try for example Rx-React I think using these libs is quite similar to using what the ELM language offers with signals. CycleJS framework does not use ReactJS but uses vdom. It share a lot of similarities with the Elm architecture (but is more easy to use in real life because it allows vdom hooks) and it uses RxJs extensively instead of functions, and can be a good source of inspiration if you want to use FRP with React. CycleJs Egghead videos are nice to understand how it works. CSP CSP (Communicating Sequential Processes) are currently popular (mostly because of Go/goroutines and core.async/ClojureScript) but you can use them also in javascript with JS-CSP. James Long has done a video explaining how it can be used with React. Sagas A saga is a backend concept that comes from the DDD / EventSourcing / CQRS world, also called "process manager". It is being popularized by the redux-saga project, mostly as a replacement to redux-thunk for handling side-effects (ie API calls etc). Most people currently think it only services for side-effects but it is actually more about decoupling components. It is more of a compliment to a Flux architecture (or Redux) than a totally new communication system, because the saga emit Flux actions at the end. The idea is that if you have widget1 and widget2, and you want them to be decoupled, you can't fire action targeting widget2 from widget1. So you make widget1 only fire actions that target itself, and the saga is a "background process" that listens for widget1 actions, and may dispatch actions that target widget2. The saga is the coupling point between the 2 widgets but the widgets remain decoupled. If you are interested take a look at my answer here Conclusion If you want to see an example of the same little app using these different styles, check the branches of this repository. I don't know what is the best option in the long term but I really like how Flux looks like event-sourcing. If you don't know event-sourcing concepts, take a look at this very pedagogic blog: Turning the database inside out with apache Samza, it is a must-read to understand why Flux is nice (but this could apply to FRP as well) I think the community agrees that the most promising Flux implementation is Redux, which will progressively allow very productive developer experience thanks to hot reloading. Impressive livecoding ala Bret Victor's Inventing on Principle video is possible!
OK, there are few ways to do it, but I exclusively want focus on using store using Redux which makes your life much easier for these situations rather than give you a quick solution only for this case, using pure React will end up mess up in real big application and communicating between Components becomes harder and harder as the application grows... So what Redux does for you? Redux is like local storage in your application which can be used whenever you need data to be used in different places in your application... Basically, Redux idea comes from flux originally, but with some fundamental changes including the concept of having one source of truth by creating only one store... Look at the graph below to see some differences between Flux and Redux... Consider applying Redux in your application from the start if your application needs communication between Components... Also reading these words from Redux Documentation could be helpful to start with: As the requirements for JavaScript single-page applications have become increasingly complicated, our code must manage more state than ever before. This state can include server responses and cached data, as well as locally created data that has not yet been persisted to the server. UI state is also increasing in complexity, as we need to manage active routes, selected tabs, spinners, pagination controls, and so on. Managing this ever-changing state is hard. If a model can update another model, then a view can update a model, which updates another model, and this, in turn, might cause another view to update. At some point, you no longer understand what happens in your app as you have lost control over the when, why, and how of its state. When a system is opaque and non-deterministic, it's hard to reproduce bugs or add new features. As if this wasn't bad enough, consider the new requirements becoming common in front-end product development. As developers, we are expected to handle optimistic updates, server-side rendering, fetching data before performing route transitions, and so on. We find ourselves trying to manage a complexity that we have never had to deal with before, and we inevitably ask the question: is it time to give up? The answer is no. This complexity is difficult to handle as we're mixing two concepts that are very hard for the human mind to reason about: mutation and asynchronicity. I call them Mentos and Coke. Both can be great in separation, but together they create a mess. Libraries like React attempt to solve this problem in the view layer by removing both asynchrony and direct DOM manipulation. However, managing the state of your data is left up to you. This is where Redux enters. Following in the steps of Flux, CQRS, and Event Sourcing, Redux attempts to make state mutations predictable by imposing certain restrictions on how and when updates can happen. These restrictions are reflected in the three principles of Redux.
This is the way I handled this. Let's say you have a <select> for Month and a <select> for Day. The number of days depends on the selected month. Both lists are owned by a third object, the left panel. Both <select> are also children of the leftPanel <div> It's a game with the callbacks and the handlers in the LeftPanel component. To test it, just copy the code into two separated files and run the index.html. Then select a month and see how the number of days changes. dates.js /** #jsx React.DOM */ var monthsLength = [0,31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; var MONTHS_ARR = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]; var DayNumber = React.createClass({ render: function() { return ( <option value={this.props.dayNum}>{this.props.dayNum}</option> ); } }); var DaysList = React.createClass({ getInitialState: function() { return {numOfDays: 30}; }, handleMonthUpdate: function(newMonthix) { this.state.numOfDays = monthsLength[newMonthix]; console.log("Setting days to " + monthsLength[newMonthix] + " month = " + newMonthix); this.forceUpdate(); }, handleDaySelection: function(evt) { this.props.dateHandler(evt.target.value); }, componentDidMount: function() { this.props.readyCallback(this.handleMonthUpdate) }, render: function() { var dayNodes = []; for (i = 1; i <= this.state.numOfDays; i++) { dayNodes = dayNodes.concat([<DayNumber dayNum={i} />]); } return ( <select id={this.props.id} onChange = {this.handleDaySelection}> <option value="" disabled defaultValue>Day</option> {dayNodes} </select> ); } }); var Month = React.createClass({ render: function() { return ( <option value={this.props.monthIx}>{this.props.month}</option> ); } }); var MonthsList = React.createClass({ handleUpdate: function(evt) { console.log("Local handler:" + this.props.id + " VAL= " + evt.target.value); this.props.dateHandler(evt.target.value); return false; }, render: function() { var monthIx = 0; var monthNodes = this.props.data.map(function (month) { monthIx++; return ( <Month month={month} monthIx={monthIx} /> ); }); return ( <select id = {this.props.id} onChange = {this.handleUpdate}> <option value="" disabled defaultValue>Month</option> {monthNodes} </select> ); } }); var LeftPanel = React.createClass({ dayRefresh: function(newMonth) { // Nothing - will be replaced }, daysReady: function(refreshCallback) { console.log("Regisering days list"); this.dayRefresh = refreshCallback; }, handleMonthChange: function(monthIx) { console.log("New month"); this.dayRefresh(monthIx); }, handleDayChange: function(dayIx) { console.log("New DAY: " + dayIx); }, render: function() { return( <div id="orderDetails"> <DaysList id="dayPicker" dateHandler={this.handleDayChange} readyCallback = {this.daysReady} /> <MonthsList data={MONTHS_ARR} id="monthPicker" dateHandler={this.handleMonthChange} /> </div> ); } }); React.renderComponent( <LeftPanel />, document.getElementById('leftPanel') ); And the HTML for running the left panel component index.html <!DOCTYPE html> <html> <head> <title>Dates</title> <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script> <script src="//fb.me/react-0.11.1.js"></script> <script src="//fb.me/JSXTransformer-0.11.1.js"></script> </head> <style> #dayPicker { position: relative; top: 97px; left: 20px; width: 60px; height: 17px; } #monthPicker { position: relative; top: 97px; left: 22px; width: 95px; height: 17px; } select { font-size: 11px; } </style> <body> <div id="leftPanel"> </div> <script type="text/jsx" src="dates.js"></script> </body> </html>
I saw that the question is already answered, but if you'd like to learn more details, there are a total of 3 cases of communication between components: Case 1: Parent to Child communication Case 2: Child to Parent communication Case 3: Not-related components (any component to any component) communication
I once was where you are right now, as a beginner you sometimes feel out of place on how the react way to do this. I'm gonna try to tackle the same way I think of it right now. States are the cornerstone for communication Usually what it comes down to is the way that you alter the states in this component in your case you point out three components. <List /> : Which probably will display a list of items depending on a filter <Filters />: Filter options that will alter your data. <TopBar />: List of options. To orchestrate all of this interaction you are going to need a higher component let's call it App, that will pass down actions and data to each one of this components so for instance can look like this <div> <List items={this.state.filteredItems}/> <Filter filter={this.state.filter} setFilter={setFilter}/> </div> So when setFilter is called it will affect the filteredItem and re-render both component;. In case this is not entirely clear I made you an example with checkbox that you can check in a single file: import React, {Component} from 'react'; import {render} from 'react-dom'; const Person = ({person, setForDelete}) => ( <div> <input type="checkbox" name="person" checked={person.checked} onChange={setForDelete.bind(this, person)} /> {person.name} </div> ); class PeopleList extends Component { render() { return( <div> {this.props.people.map((person, i) => { return <Person key={i} person={person} setForDelete={this.props.setForDelete} />; })} <div onClick={this.props.deleteRecords}>Delete Selected Records</div> </div> ); } } // end class class App extends React.Component { constructor(props) { super(props) this.state = {people:[{id:1, name:'Cesar', checked:false},{id:2, name:'Jose', checked:false},{id:3, name:'Marbel', checked:false}]} } deleteRecords() { const people = this.state.people.filter(p => !p.checked); this.setState({people}); } setForDelete(person) { const checked = !person.checked; const people = this.state.people.map((p)=>{ if(p.id === person.id) return {name:person.name, checked}; return p; }); this.setState({people}); } render () { return <PeopleList people={this.state.people} deleteRecords={this.deleteRecords.bind(this)} setForDelete={this.setForDelete.bind(this)}/>; } } render(<App/>, document.getElementById('app'));
Extending answer of #MichaelLaCroix when a scenario is that the components can't communicate between any sort of parent-child relationship, the documentation recommends setting up a global event system. In the case of <Filters /> and <TopBar /> don't have any of the above relationship, a simple global emitter could be used like this: componentDidMount - Subscribe to event componentWillUnmount - Unsubscribe from event React.js and EventSystem code EventSystem.js class EventSystem{ constructor() { this.queue = {}; this.maxNamespaceSize = 50; } publish(/** namespace **/ /** arguments **/) { if(arguments.length < 1) { throw "Invalid namespace to publish"; } var namespace = arguments[0]; var queue = this.queue[namespace]; if (typeof queue === 'undefined' || queue.length < 1) { console.log('did not find queue for %s', namespace); return false; } var valueArgs = Array.prototype.slice.call(arguments); valueArgs.shift(); // remove namespace value from value args queue.forEach(function(callback) { callback.apply(null, valueArgs); }); return true; } subscribe(/** namespace **/ /** callback **/) { const namespace = arguments[0]; if(!namespace) throw "Invalid namespace"; const callback = arguments[arguments.length - 1]; if(typeof callback !== 'function') throw "Invalid callback method"; if (typeof this.queue[namespace] === 'undefined') { this.queue[namespace] = []; } const queue = this.queue[namespace]; if(queue.length === this.maxNamespaceSize) { console.warn('Shifting first element in queue: `%s` since it reached max namespace queue count : %d', namespace, this.maxNamespaceSize); queue.shift(); } // Check if this callback already exists for this namespace for(var i = 0; i < queue.length; i++) { if(queue[i] === callback) { throw ("The exact same callback exists on this namespace: " + namespace); } } this.queue[namespace].push(callback); return [namespace, callback]; } unsubscribe(/** array or topic, method **/) { let namespace; let callback; if(arguments.length === 1) { let arg = arguments[0]; if(!arg || !Array.isArray(arg)) throw "Unsubscribe argument must be an array"; namespace = arg[0]; callback = arg[1]; } else if(arguments.length === 2) { namespace = arguments[0]; callback = arguments[1]; } if(!namespace || typeof callback !== 'function') throw "Namespace must exist or callback must be a function"; const queue = this.queue[namespace]; if(queue) { for(var i = 0; i < queue.length; i++) { if(queue[i] === callback) { queue.splice(i, 1); // only unique callbacks can be pushed to same namespace queue return; } } } } setNamespaceSize(size) { if(!this.isNumber(size)) throw "Queue size must be a number"; this.maxNamespaceSize = size; return true; } isNumber(n) { return !isNaN(parseFloat(n)) && isFinite(n); } } NotificationComponent.js class NotificationComponent extends React.Component { getInitialState() { return { // optional. see alternative below subscriber: null }; } errorHandler() { const topic = arguments[0]; const label = arguments[1]; console.log('Topic %s label %s', topic, label); } componentDidMount() { var subscriber = EventSystem.subscribe('error.http', this.errorHandler); this.state.subscriber = subscriber; } componentWillUnmount() { EventSystem.unsubscribe('error.http', this.errorHandler); // alternatively // EventSystem.unsubscribe(this.state.subscriber); } render() { } }
There is such possibility even if they are not Parent - Child relationship - and that's Flux. There is pretty good (for me personally) implementation for that called Alt.JS (with Alt-Container). For example you can have Sidebar that is dependent on what is set in component Details. Component Sidebar is connected with SidebarActions and SidebarStore, while Details is DetailsActions and DetailsStore. You could use then AltContainer like that <AltContainer stores={{ SidebarStore: SidebarStore }}> <Sidebar/> </AltContainer> {this.props.content} Which would keep stores (well I could use "store" instead of "stores" prop). Now, {this.props.content} CAN BE Details depending on the route. Lets say that /Details redirect us to that view. Details would have for example a checkbox that would change Sidebar element from X to Y if it would be checked. Technically there is no relationship between them and it would be hard to do without flux. BUT WITH THAT it is rather easy. Now let's get to DetailsActions. We will create there class SiteActions { constructor() { this.generateActions( 'setSiteComponentStore' ); } setSiteComponent(value) { this.dispatch({value: value}); } } and DetailsStore class SiteStore { constructor() { this.siteComponents = { Prop: true }; this.bindListeners({ setSiteComponent: SidebarActions.COMPONENT_STATUS_CHANGED }) } setSiteComponent(data) { this.siteComponents.Prop = data.value; } } And now, this is the place where magic begin. As You can see there is bindListener to SidebarActions.ComponentStatusChanged which will be used IF setSiteComponent will be used. now in SidebarActions componentStatusChanged(value){ this.dispatch({value: value}); } We have such thing. It will dispatch that object on call. And it will be called if setSiteComponent in store will be used (that you can use in component for example during onChange on Button ot whatever) Now in SidebarStore we will have constructor() { this.structures = []; this.bindListeners({ componentStatusChanged: SidebarActions.COMPONENT_STATUS_CHANGED }) } componentStatusChanged(data) { this.waitFor(DetailsStore); _.findWhere(this.structures[0].elem, {title: 'Example'}).enabled = data.value; } Now here you can see, that it will wait for DetailsStore. What does it mean? more or less it means that this method need to wait for DetailsStoreto update before it can update itself. tl;dr One Store is listening on methods in a store, and will trigger an action from component action, which will update its own store. I hope it can help you somehow.
If you want to explore options of communicating between components and feel like it is getting harder and harder, then you might consider adopting a good design pattern: Flux. It is simply a collection of rules that defines how you store and mutate application wide state, and use that state to render components. There are many Flux implementations, and Facebook's official implementation is one of them. Although it is considered the one that contains most boilerplate code, but it is easier to understand since most of the things are explicit. Some of Other alternatives are flummox fluxxor fluxible and redux.
The following code helps me to setup communication between two siblings. The setup is done in their parent during render() and componentDidMount() calls. It is based on https://reactjs.org/docs/refs-and-the-dom.html Hope it helps. class App extends React.Component<IAppProps, IAppState> { private _navigationPanel: NavigationPanel; private _mapPanel: MapPanel; constructor() { super(); this.state = {}; } // `componentDidMount()` is called by ReactJS after `render()` componentDidMount() { // Pass _mapPanel to _navigationPanel // It will allow _navigationPanel to call _mapPanel directly this._navigationPanel.setMapPanel(this._mapPanel); } render() { return ( <div id="appDiv" style={divStyle}> // `ref=` helps to get reference to a child during rendering <NavigationPanel ref={(child) => { this._navigationPanel = child; }} /> <MapPanel ref={(child) => { this._mapPanel = child; }} /> </div> ); } }
Oddly nobody mentioned mobx. The idea is similar to redux. If I have a piece of data that multiple components are subscribed to it, then I can use this data to drive multiple components.