Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactJS - React.Children.forEach - Can I get the child component name?

I have a React (15.5.4) component with many children, some of which are HTML elements and some are other React components.

I'm using server rendering and need the same behavior on the server and client. The client will be using the production build of React.

I need to iterate over the children and identify a specific type of React component. So my first thought was to iterate using React.Children.forEach() and look for the component name.

React.Children.forEach(this.props.children, child => {
  console.log('name =', child.name)
})

It seems child.name and child.displayName don't exist.

Now, child.type exists, and is either a string (for HTML elements) like "ul" or a function (for React components).

When it's a function, I can use lodash/get like this const type = get(child, 'type.name', '') to get the component name. However, this only seems to work on the server, not in the client side production build, where it returns a string: "t". It looks like the development build uses my component name for the function, but the production build renames it to t(). So I can't use child.type.name.

How do I:

  1. Iterate over a components children and identify a specific type of component..?
  2. Which works in both the development and production React builds..?
like image 958
Stephen Last Avatar asked May 11 '17 10:05

Stephen Last


1 Answers

You can set the component's name in the property displayName. If you're using ES6 classes, you can set a static property called displayName into component's class. Then, you'll be able to get the child name with child.type.displayName.

const FirstChild = ({ name }) => <li>{name}</li>;
FirstChild.displayName = 'FirstChild';

const SecondChild = ({ name }) => <li>{name}</li>;
SecondChild.displayName = 'SecondChild';

class ThirdChild extends React.Component {
  static displayName = 'ThirdChild';
  
  render() {
    return (
      <li>{this.props.name}</li>
    );
  }
  
}

class Parent extends React.Component {
  componentDidMount() {
    React.Children.forEach(this.props.children, child => {
      console.log('name =', child.type.displayName);
    })
  }
  
  render() {
    return (
      <ul>{this.props.children}</ul>
    );
  }
}

class App extends React.Component {
  render() {
    return (
      <Parent>
        <FirstChild name='1st child value' />
        <SecondChild name='2nd child value' />
        <ThirdChild name='3rd child value' />
      </Parent>
    );
  }
}


ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
like image 197
Julio Betta Avatar answered Sep 18 '22 12:09

Julio Betta