einav
einav

Reputation: 609

React - Get the component name in functional components

I want on every component in my app to add attribute component-name="componentX". I don't want to do it hard coded when creating a component but to find a generic way to find the component name and set it in the attribute.

I know there is the displayName property but it's only for class component.

I have a lot of functional components. How can I achieve it?

Thanks!

Upvotes: 4

Views: 12645

Answers (1)

Sagiv b.g
Sagiv b.g

Reputation: 31024

If you wrap children you can access the child.type.name to get the component / function name.

Here is a small example:

class LogNames extends React.Component {
  render() {
    const { children } = this.props;
    React.Children.forEach(children,child =>{
      console.log(child.type.name)
    });
    return children;
  }
}

class Child extends React.Component {
  render() {
    return <div>A Child</div>
  }
}

const Child2 = () => <div>Child 2</div>

class App extends React.Component {
  render() {
    return (
      <div>
        <LogNames>
          <Child/>
        </LogNames>
        <LogNames>
          <Child2 />
        </LogNames>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<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="root" />

Just noticed you want to set an attribute on the DOM as well, so i added another example that does just that (open devtools to see the attributes):

class WithNameAttr extends React.Component {

  componentDidMount(){
    const {children} = this.props;

    // get a ref to the current node
    const node = ReactDOM.findDOMNode(this);

    // force and return a signle child
    const child = React.Children.only(children);

    // set name attribute (if available) 
    const name = child.type.name;
    name && node.setAttribute('component-name', name);
  }

  render() {
    return this.props.children;
  }
}

class Child extends React.Component {
  render() {
    return <div>A Child</div>
  }
}

const Child2 = () => <div>Child 2</div>

class App extends React.Component {
  render() {
    return (
      <div>
        <WithNameAttr>
          <Child />
        </WithNameAttr>
        <WithNameAttr>
          <Child2 />
        </WithNameAttr>
        <WithNameAttr>
          <div>dom elemetns doesnt have names</div>
        </WithNameAttr>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<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="root"/>

Upvotes: 6

Related Questions