【问题标题】:ReactJS - How can I access the displayName of a component using javascript?ReactJS - 如何使用 javascript 访问组件的 displayName?
【发布时间】:2014-09-02 17:15:51
【问题描述】:

我正在构建一些 React 组件,有时希望通过 displayName 将正在渲染的组件类型记录到控制台,JSX 在显示组件名称时使用该类型。

从组件的上下文中,我如何访问displayName 属性?

例如如何使本例中的console.log 语句显示组件的显示名称?

var Hello = React.createClass({
    displayName: 'HeyHey',

    render: function() {
        console.log(this.displayName);

        return <div>Hello {this.props.name}</div>;
    }
});

控制台中的预期输出:

嘿嘿

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    下面是完整的代码 sn-p,详细说明了如何获取和设置 class 组件和无状态功能组件的“名称”。

    您从class 组件的名称或代码中的无状态功能组件的名称​​免费获得组件上的name 属性。但是请注意,在匿名类/函数的情况下,这将是未定义的,也可以通过代码缩小来消除/更改。

    如果您需要自定义,您可以class 组件或无状态功能组件上定义自定义displayName 属性。这对于高阶组件特别有用。它也将始终在缩小后存活。

    class 上,这是可能不明显的部分namedisplayName类本身的属性。这就是为什么在组件实例中你必须使用this.constructor.name/this.constructor.displayName,并且对组件实例的引用你使用Component.name/Component.displayName。下面的代码在实践中展示了这一点。

    使用组件名称seems to be的最佳实践:

    • 尝试使用displayName
    • 如果未定义,请尝试使用name
    • 这是未定义的,回退到像'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>

    【讨论】:

    • WrappedComponent.displayName 返回undefined,但name 效果很好
    • @vsync 可能是我的误解,但我不确定你的意思。你说的是我上面sn-p中的代码吗?如果你运行它,你会看到WrappedComponent.displayName not 未定义——它在输出中打印为'SFComponentCustom' :-)
    【解决方案2】:

    它可以作为公共财产this.constructor.displayName使用。

    【讨论】:

    • 注意,只有组件挂载时,构造函数才可用
    • 什么是生产中的显示名称(当 webpack 最小化脚本时)。我得到“t”而不是“MyComponent”。如何获取名称“MyComponent”,因为我在代码中需要它?
    • 更新:您可以使用this.constructor.name访问该名称。我正在使用 React 15.4
    • this.constructor.name 将返回函数的名称,而不是 React displayName。它与 React 无关,而是一个 JavaScript 特性,(function Blah(){}).name === 'Blah'
    • this.constructor.name 仅在开发模式下工作,一旦构建和打包,它就不再适合我了
    【解决方案3】:

    你可以在this._descriptor.type找到它

    Hello <div>{this._descriptor.type.displayName}</div>
    

    demo

    仅用于测试;它可能随时停止工作。它不太可能在 0.12 中工作。

    【讨论】:

    • 谢谢!顺便说一句 - 你是怎么知道它在哪里的?您知道吗,还是您搜索了来源或其他什么?我尝试将组件json化,并搜索react-with-addons的来源,但没有立即看到......
    • 我不相信它被记录在案;我刚刚在控制台上找到了它。
    • @BradParks 我刚刚检查过,this.type 在 master 上未定义,所以它可能不会在 0.11 中。我更新了它以包含在 0.10 和 master 中工作的东西。
    • @BradParks: “因为它听起来更适合未来” 属性名称以_ 为前缀的事实意味着它是私有属性。它可能随时更改,根本不是未来的证据。
    • 我知道任何名称中带有 _ 的属性都是私有的 - 但由于“this.type”方式不在 master 中 - 而私有方式是私有方式仍然更“面向未来” - 但我明白你在说什么;-)
    猜你喜欢
    • 2014-08-11
    • 2019-08-01
    • 1970-01-01
    • 2016-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-21
    相关资源
    最近更新 更多