How to check how many React children have a certain prop?
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.
Answer
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
Related Questions
- → How to update data attribute on Ajax complete
- → October CMS - Radio Button Ajax Click Twice in a Row Causes Content to disappear
- → Octobercms Component Unique id (Twig & Javascript)
- → Passing a JS var from AJAX response to Twig
- → Laravel {!! Form::open() !!} doesn't work within AngularJS
- → DropzoneJS & Laravel - Output form validation errors
- → Import statement and Babel
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM