4

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!

1

1 Answer 1

6

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"/>

Sign up to request clarification or add additional context in comments.

2 Comments

Question out of curiosity, what is the difference between type.name and displayName? Because from experience I have encountered problems with type.name as it changed after builds.
@TomasEglinskas Not sure where do you see the displayName (i think it has been changed since react 15, maybe you mean constructor.name)? anyway don't forget we are referencing a child here (that can also be a function component and not a class)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.