Reputation: 1929
I have two types of components. Let's call them Outer and Inner. Imagine something like this:
<Outer>
<h4>{this.prop.title} ({this.state.withX}/{this.state.total})</h4>
<Inner isX/>
<Inner isX/>
<Inner/>
<Inner/>
</Outer>
I have this function:
getInitialState: function() {
return {
total: React.Children.count(this.props.children),
withX: /// ??? ///
};
}
How do I get that value? I was trying to get something like this:
withX: function() {
var counter = React.Children.forEach(this.props.children, function(child) {
// if...
return //something
});
return counter;
}
But... I feel it'll get me nowhere.
Upvotes: 34
Views: 55663
Reputation: 3612
React now has React.Children.count(children)
method documented here https://react.dev/reference/react/Children#children-count
UPDATE: upon reflection, I'm not sure this actually answers the question, but will leave here anyway as people have already voted on it.
Upvotes: 55
Reputation: 159115
When you iterate over the children, you can inspect their props. For instance, using the forEach
method you have above, you could do something like this:
withX: function() {
var counter = 0;
React.Children.forEach(this.props.children, function(child) {
if (child.props.isX) counter++;
});
return counter;
}
React also provides a toArray
helper that lets you do the same thing using the nice array methods JS provides:
return React.Children.toArray(this.props.children).filter(function(child) {
return child.props.isX;
}).length;
If you're using ES6, can do this quite succinctly with an arrow function:
return React.Children.toArray(this.props.children).filter(c => c.props.isX).length;
The only catch is that, if Outer
is doing the counting, then Outer
also needs to render the h4
. Here's a full example:
const App = React.createClass({
render() {
return (
<Outer title="Things">
<Inner isX/>
<Inner isX/>
<Inner/>
<Inner/>
</Outer>
);
}
});
const Outer = React.createClass({
getInitialState() {
return {
total: React.Children.count(this.props.children),
withX: this.countChildrenWithX(this.props.children)
};
},
countChildrenWithX(children) {
const { toArray } = React.Children;
return toArray(children).filter(c => c.props.isX).length;
},
render() {
return (
<div>
<h4>{this.props.title} ({this.state.withX}/{this.state.total})</h4>
<hr />
{this.props.children}
</div>
);
}
});
const Inner = React.createClass({
render() {
return <div>Inner - withX = {String(!!this.props.isX)}</div>;
}
});
And here's a working JS Bin to demonstrate: https://jsbin.com/xameyun/edit?js,output
Upvotes: 35