Suppose you have a Dropdown
React component:
var Dropdown = React.createClass({
render: function () {
return (
<div className="dropdown" />
);
},
itemSelected: function (item) {
this.setState({
value: item.props.value
});
}
});
And a corresponding Option
:
var Option = React.createClass({
_onClick: function () {
this.props.onSelect(this);
},
render: function () {
return (
<div className="item" onClick={this._onClick}>{this.props.value}</div>
);
}
});
Now imagine you use these components together like so:
var ColorForm = React.createClass({
render: function () {
return (
<div>
<label>Pick a color</label>
<Dropdown>
<Option onSelect={???.itemSelected} value="red" />
<Option onSelect={???.itemSelected} value="blue" />
<Option onSelect={???.itemSelected} value="green" />
</Dropdown>
</div>
);
}
});
Notice the onSelect={???.itemSelected}
bit.
How do I pass the parent dropdown's itemSelected
method to each child?
I know that if I create a custom dropdown class, it's easy, but this defeats the purpose of components:
var ColorDropdown = React.createClass({
render: function () {
return (
<div className="dropdown">
<Option onSelect={this.itemSelected} value="red" />
<Option onSelect={this.itemSelected} value="blue" />
<Option onSelect={this.itemSelected} value="green" />
</div>
);
},
itemSelected: function (item) {
this.setState({
value: item.props.value
});
}
});
You can add an onSelect
attribute to child Option
elements inside the Dropdown::render
method using a combination of this.props.children
, React.Children.map
, and React.cloneWithProps
:
var React = require('react/addons');
var Option = require('./Option');
var Dropdown = React.createClass({
itemSelected: function (item) {
this.setState({
value: item.value
});
},
render: function () {
var self = this;
var children = React.Children.map(this.props.children, function (child) {
if (child.type !== Option.type) {
return child;
} else {
return Reat.cloneWithProps(child, {
onSelect: function () {
self.itemSelected(this);
}
});
}
});
return (
<div className="dropdown">
{children}
</div>
);
}
});
So now you don't need to set onSelect
for each Item
child:
var ColorForm = React.createClass({
render: function () {
return (
<div>
<label>Pick a color</label>
<Dropdown>
<Option value="red" />
<Option value="blue" />
<Option value="green" />
</Dropdown>
</div>
);
}
});
See the similar code for radio buttons: http://jaketrent.com/post/send-props-to-children-react/