【问题标题】:ReactJS - React.Children.forEach - Can I get the child component name?ReactJS - React.Children.forEach - 我可以获取子组件名称吗?
【发布时间】:2017-10-10 07:36:23
【问题描述】:

我有一个包含许多子元素的 React (15.5.4) 组件,其中一些是 HTML 元素,一些是其他 React 组件。

我正在使用服务器渲染,并且需要在服务器和客户端上具有相同的行为。客户端将使用 React 的生产版本。

我需要遍历子元素并确定特定类型的 React 组件。所以我的第一个想法是使用React.Children.forEach() 进行迭代并查找组件名称。

React.Children.forEach(this.props.children, child => {
  console.log('name =', child.name)
})

child.namechild.displayName 似乎不存在。

现在,child.type 存在,它要么是一个字符串(对于 HTML 元素),比如 "ul",要么是一个函数(对于 React 组件)。

当它是一个函数时,我可以像这样使用lodash/get const type = get(child, 'type.name', '') 来获取组件名称。 然而,这似乎只在服务器上工作,而不是在客户端生产版本中,它返回一个字符串:"t"。看起来开发版本使用我的组件名称作为功能,但生产版本将其重命名为t()。所以我不能使用child.type.name

我该怎么做:

  1. 遍历子组件并识别特定类型的组件..?
  2. 哪个在开发和生产 React 构建中都有效..?

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    您可以在属性displayName 中设置组件的名称。如果您使用的是 ES6 类,您可以在组件的类中设置一个名为 displayName 的静态属性。然后,您将能够使用child.type.displayName 获取子名称。

    const FirstChild = ({ name }) => <li>{name}</li>;
    FirstChild.displayName = 'FirstChild';
    
    const SecondChild = ({ name }) => <li>{name}</li>;
    SecondChild.displayName = 'SecondChild';
    
    class ThirdChild extends React.Component {
      static displayName = 'ThirdChild';
      
      render() {
        return (
          <li>{this.props.name}</li>
        );
      }
      
    }
    
    class Parent extends React.Component {
      componentDidMount() {
        React.Children.forEach(this.props.children, child => {
          console.log('name =', child.type.displayName);
        })
      }
      
      render() {
        return (
          <ul>{this.props.children}</ul>
        );
      }
    }
    
    class App extends React.Component {
      render() {
        return (
          <Parent>
            <FirstChild name='1st child value' />
            <SecondChild name='2nd child value' />
            <ThirdChild name='3rd child value' />
          </Parent>
        );
      }
    }
    
    
    ReactDOM.render(<App />, document.getElementById("app"));
    <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="app"></div>

    【讨论】:

    • 谢谢!我一直在寻找已经在组件上设置的东西,但是使用 FirstChild.displayName = 'FirstChild' 设置我自己的静态属性效果很好。
    • 谢谢!很高兴能提供帮助。
    • 有没有解释为什么部署的构建返回't'?
    • 没问题!我也遇到过同样的情况,但没有解释为什么会这样。但是,您的答案确实有效。
    • 如何让static displayName = 'ThirdChild'; 工作?它对我不起作用。
    【解决方案2】:

    如果你使用 Babel,你可以使用这个 Babel 插件来自动设置displayName,这样child.type.displayName 就等于你为组件命名的字符串:

    https://www.npmjs.com/package/babel-plugin-add-react-displayname

    它易于安装和使用,只需阅读说明并确保将插件名称 add-react-displayname 添加到 .babelrc 文件中的插件数组中。

    【讨论】:

      【解决方案3】:

      使用 es6 扩展运算符:

              React.Children.forEach(children, child => {
                  const childType = { ...child.type }
                  console.log('child', childType.displayName)
              })
      

      【讨论】:

        【解决方案4】:

        注意:仅工作开发模式

        function MyComponent() (
          return <AnotherComponent />
        )
        
        // In React Function Component ?
        function AnotherComponent({children}) {
        
            console.log(children.type.name) // result = 'MyComponent' 
        
            return (<div></div>)
        }
        
        // In React Class Component ?
        export default class Extends React.Component {
        
            console.log(this.children.type.name) // result = 'MyComponent' 
        
            render() {
              return (<div></div>)
            }
        
        }
        

        【讨论】:

        • 此解决方案仅在 React 处于开发模式时有效,而在为生产构建时无效。 name 属性(私有)在生产环境中被缩小和更改,因此不是预期的名称。
        • @JosephShambrook 好点,但这仍然是非常有价值的信息。不过可能根本对 OP 没有帮助。
        猜你喜欢
        • 1970-01-01
        • 2014-03-06
        • 1970-01-01
        • 1970-01-01
        • 2023-03-16
        • 1970-01-01
        • 2015-11-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多