ReactJS - How can I access the displayName of a component using javascript?
I'm building some React components and sometimes would like to log to the console the type of component that's being rendered, by displayName
, which JSX uses when displaying the name of a component.
From the context of a component, how can I access the displayName
property?
e.g. how can I make the console.log
statement in this example show the displayName of the component?
var Hello = React.createClass({
displayName: 'HeyHey',
render: function() {
console.log(this.displayName);
return <div>Hello {this.props.name}</div>;
}
});
Intended output in console:
HeyHey
It's available as the public property this.constructor.displayName
.
Below is a full code snippet illustrating in detail how to both get and set the 'name' of both class
Components and stateless functional Components.
You get a name
property on a Component for free, from name of the class
Component or the stateless functional Component in code. However be aware that this will be undefined in the case of anonymous classes/functions, and can also be wiped out / changed by code minification.
You may define a custom displayName
property on the class
Component or stateless functional Component, if you need to customise. This is especially useful for higher order components. It will also always survive minification.
On a class
, and here is the part that may not be obvious, the name
and displayName
are properties on the class itself. Thats why from within the Component instance you have to use this.constructor.name
/ this.constructor.displayName
and with a reference to the Component instance you use Component.name
/ Component.displayName
. The code below shows this in practice.
Best practice for using a Component's name seems to be:
- Try to use
displayName
- If that's undefined, try to use
name
- It that's undefined, fall back to a hardcoded string like
'Component'
/'Anonymous'
class ClassComponent extends React.Component {
componentDidMount () {
if (!this.props.wrapped) {
console.log('ClassComponent')
console.log(` displayName: ${this.constructor.displayName}`)
console.log(` name: ${this.constructor.name}\n\n`)
}
}
render () {
return <div>ClassComponent {this.props.wrapped && '(wrapped)'}</div>
}
}
ClassComponent.displayName =
'ClassComponentCustom'
const SFComponent = (props) => (
<div>SFComponent {props.wrapped && '(wrapped)'}</div>
)
SFComponent.displayName =
'SFComponentCustom'
const wrap = (WrappedComponent) => {
class Wrapper extends React.Component {
componentDidMount () {
console.log('HOC')
console.log(` displayName: ${this.constructor.displayName}`)
console.log(` name: ${this.constructor.name}`)
console.log(` wrapping a Component with:`)
console.log(` displayName: ${WrappedComponent.displayName}`)
console.log(` name: ${WrappedComponent.name}\n\n`)
}
render () {
return <WrappedComponent wrapped />
}
}
// for the wrapped component
// check for displayName for something more descriptive,
// else fall back to name
const wrappedComponentName =
WrappedComponent.displayName ||
WrappedComponent.name
Wrapper.displayName =
`WrapperCustom<${wrappedComponentName}>`
return Wrapper
}
const WrappedClassComponent = wrap(ClassComponent)
const WrappedSFComponent = wrap(SFComponent)
const Example = () => (
<div className="example">
<ClassComponent />
<SFComponent />
<WrappedClassComponent />
<WrappedSFComponent />
</div>
)
ReactDOM.render(
<Example />,
document.getElementById('root')
)
.example > div {
font-family: 'Arial';
font-size: 14px;
padding: 5px 10px;
margin-bottom: 10px;
background: rgb(240,240,240);
border-radius: 4px;
}
<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"></div>
You can find it on this._descriptor.type
Hello <div>{this._descriptor.type.displayName}</div>
demo
Only use this for testing; it might stop working at any point. It's unlikely to work in 0.12.