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.
Best 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.
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.
Parent with single child: using the value it passes to the child
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.
JsFiddle
It is also possible to use
this.handleChildClick.bind(null,childIndex)
and then usethis.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:
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:
And access the DOM node in the parent with
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...:
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(...)
orchildComponent.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:
The parent can be either a class (and it can eventually manage the state itself, but I'm passing it as props here:
But it can also be simplified if it does not need to manage state:
JsFiddle
PERF WARNING (apply to ES5/ES6): if you are using
PureComponent
orshouldComponentUpdate
, the above implementations will not be optimized by default because usingonClick={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 tothis
in class constructor) so thatPureComponent
optimization can kick in, or you can implement your ownshouldComponentUpdate
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:
In this case you could optimize the Child component by using: