Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 243
Tomasz Gałkowski Avatar asked Dec 25 '15 20:12

Tomasz Gałkowski


People also ask

How do you check props in React?

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.

How many props are too many React?

I follow this rule of thumb: Three props is fine. Five props is a code smell. More than seven props is a disaster.

Can props be pass from child to parent React?

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.


2 Answers

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.

like image 149
Chris Edwards Avatar answered Sep 22 '22 17:09

Chris Edwards


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

like image 40
Michelle Tilley Avatar answered Sep 22 '22 17:09

Michelle Tilley