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.
Custom validators for type checking React props Usually, you need to define some custom validation logic for component props, for example, to ensure that a prop is passed a valid email address. prop-types allows you to define custom validation functions that you can use for type checking props.
I follow this rule of thumb: Three props is fine. Five props is a code smell. More than seven props is a disaster.
Reactjs allows one-way data binding, meaning passing data down the hierarchy from parent to child. To pass data from a child component to its parent, we can call a parent function from the child component with arguments.
React now has React.Children.count(children)
method documented here https://facebook.github.io/react/docs/react-api.html#react.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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With