React.cloneElement only takes a single element, but this.props.children is a collection of elements (regardless of whether you only send in one child).
So in order to clone these elements you have to iterate over them
{React.Children.map(this.props.children, (element, idx) => {
return React.cloneElement(element, { ref: idx });
})}
This code will populate this.refs so that for each child element you can access it's ref by index, e.g. this.refs[0]
,this.refs[1]
etc... See Example A below.
If you only expect one element and just want to clone that element, then simply take the first element from the this.props.children
collection. But be aware that it is not a simple array, so you must use a React helper method: React.Children.only.
Then just clone the element and pass any ref you would like to use:
var onlyChild = React.Children.only(this.props.children);
var clone = React.cloneElement(onlyChild, { ref: "test" });
See also Example B.
Example A (Fiddle here)
var P = React.createClass({
render: function() {
return <div>Parent<br/>
{React.Children.map(this.props.children, (element, idx) => {
return React.cloneElement(element, { ref: idx });
})}
</div>;
},
componentDidMount: function(prevProps, prevState) {
ReactDOM.findDOMNode(this.refs[0]).style.backgroundColor="green";
ReactDOM.findDOMNode(this.refs[1]).style.backgroundColor="blue";
ReactDOM.findDOMNode(this.refs[2]).style.backgroundColor="red";
}
});
var C = React.createClass({
render: function() {
return <div>{this.props.text}</div>;
}
});
ReactDOM.render(
<P>
<C text="a"/>
<C text="b"/>
<C text="c"/>
</P>,
document.getElementById('container')
);
Example B (Fiddle here)
var P = React.createClass({
render: function() {
var onlyChild = React.Children.only(this.props.children);
var clone = React.cloneElement(onlyChild, { ref: "test" });
return <div>Parent<br/>
{clone}
</div>;
},
componentDidMount: function(prevProps, prevState) {
ReactDOM.findDOMNode(this.refs["test"]).style.backgroundColor="green";
}
});
var C = React.createClass({
render: function() {
return <div>{this.props.text}</div>;
}
});
ReactDOM.render(
<P>
<C text="a"/>
</P>,
document.getElementById('container')
);
Both examples assume a simple <div id='container'></div>
on the page.