51

I'm developing a React application. I have a Loading component, which is a little animation for waiting. I want to add a message in this Loading component according to the component which called it.

Here is how i call my Loading component (with this.state.displayLoading at true or false) :

class LoginForm extends React.Component {
    render() {   
        return (
            <div className="login-form-root">
                 {this.state.displayLoading && <Loading loadingFrom={?}/>}
            </div>
        );
    }
}

I want to get "LoginForm" in my variable loadingFrom, which is the className. Maybe it's not the right way to do that.

7
  • 4
    <Loading loadingFrom="LoginForm"/> Commented May 5, 2017 at 9:07
  • So your login form manages its own loading state? Depending which technology you use behind the scenes this can generate some problems Commented May 5, 2017 at 9:08
  • I would prefer to have a this.component.name or something like that, is it possible ? Commented May 5, 2017 at 9:09
  • Sure that's possible (with some extra work) however, since you add it to the component itself (in your example) there is no reason why you should make your code more complex than necessary Commented May 5, 2017 at 9:10
  • @Icepickle, yes, during our requests to our JEE API that can take few seconds, we prefer to just display a screen instead of waiting on the login page. Commented May 5, 2017 at 9:10

6 Answers 6

67

Class Components

You can use this.constructor.name to obtain the name of your component.

(Using React 16.x as of this writing)

Caveat: This won't work if you're minifying for production with Webpack.

Functional Components

https://reactjs.org/docs/react-component.html#displayname

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

14 Comments

It can work with webpack, you just have to set keep_fnames and keep_classnames to true in your production config's uglify options: github.com/LemonPi/issues_webpack_classname
@Andy Yes, most likely since I wrote this answer 3 years ago. I am happy to update it. How did the API change?
well, React now allows function components, which aren't classes, hence have no this.constructor.name. However, it seems from the docs that displayName is an official property of the React.Component class, and I believe displayName gets set automatically on function components as well.
@Andy You rock. Updated answer! 🙂
So this is interesting. A teammate of mine was calling .name on a functional component and it was working in our dev environment, but after building and pushing to a staging environment it was no longer working. We never explicitly set the name so it does exist on functional components. React 17.0.2 fwiw
|
32

Every React.Component has a property called displayName that JSX sets automatically, so theoretically you can use that property

class LoginForm extends React.Component {
    render() {   
        return (
            <div className="login-form-root">
                {this.state.displayLoading && <Loading loadingFrom={this.displayName}/>}
            </div>
        );
    }
}

UPDATE (after multiple comments saying its not working)

As per convention, react offers a code snippet to wrap getting the component name on their documentation which is the following:

function withSubscription(WrappedComponent) {
  class WithSubscription extends React.Component {/* ... */}
  WithSubscription.displayName = `WithSubscription(${getDisplayName(WrappedComponent)})`;
  return WithSubscription;
}

function getDisplayName(WrappedComponent) {
  return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}

As can be seen, they first check the display name, then the component name, and if all fails, then it will be just 'Component'

8 Comments

I get undefined for that property.
@GeorgeJempty I updated with some more information I found on the documentation site, I personally think React is a huge adaptation, but once you are used to it, it's fun to use, and to make quick prototyping, but similarily good for more complex programs, though some more "have-tos or best practises" could be in place, but this is anyhow a fairly new language
@MrColes I updated the post with some more info found on the documentation website, please note that even React doesn't really use one standard way, but I added the code with reference to the site itself for more information
@Icepickle appreciate your efforts but React is not a language. It is so different from other Javascript frameworks with their built-in two way binding. And setState being asynchronous? Ugh.
@GeorgeJempty true, framework would be a better description from my side 😊 I thought wtf aswell when first working with it but after working a while longer with it, I do like it
|
3

For HOCs: you can use WrappedComponent.name

Comments

2

To make it work after webpack build you can assign a property to the function

function MyComponent() {
  return (
    <div />
  );
}
MyComponent.componentName = 'MyComponent';

function ParentComponent({ children }) {
  console.log("Children name", children.type.componentName);
}

2 Comments

This was my right answer. Everyone talking about class components, how about functional components. Getting the 'children name' works in development mode, but not after build, Doing it the way it's done in this answer makes .componentName accessible in the type object in production mode. Like so children.type.componentName
sorry if this is out of context, but you can just use component.name. no need to set componentName, you already get that for free.
-1

After searching with debugger, in newer versions you should use this._reactInternalFiber.elementType.name instead of this._reactInternalInstance.getName()

2 Comments

I don't think it's safe to use any framework variable that starts with underscore or has 'internal' in it.
Indeed. Why? Because it's liable to change without you knowing it (you're not supposed to use it, so why would they warn you).
-4

You don't need it to be dynamic since you are writing the component yourself and can pass it as a string

class LoginForm extends React.Component {
    render() {   
        return (
            <div className="login-form-root">
                 {this.state.displayLoading && <Loading loadingFrom="LoginForm "/>}
            </div>
        );
    }
}

However if you still need to access the name of the component, you could define the displayName property on the component

class LoginForm extends React.Component {
   static displayName = 'LoginForm';
    render() {   
        return (
            <div className="login-form-root">
                 {this.state.displayLoading && <Loading loadingFrom="LoginForm "/>}
            </div>
        );
    }
}

and access it like Component.displayName.

1 Comment

Component.displayName is undefined for me. Hence I use Component.name. Seams to give me what I want.

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.