ReactJS - React.Children.forEach - 我可以获得子组件名称吗?

IT技术 javascript reactjs
2021-05-11 04:46:41

我有一个 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 构建中都有效..?
4个回答

您可以在属性中设置组件的名称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>

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

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

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

使用 es6 扩展运算符:

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

注意:仅工作开发模式

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>)
    }

}