ReactJs:this.props.children 的 PropTypes 应该是什么?

ReactJs: What should the PropTypes be for this.props.children?

给定一个呈现其 children:

的简单组件
class ContainerComponent extends Component {
  static propTypes = {
    children: PropTypes.object.isRequired,
  }

  render() {
    return (
      <div>
        {this.props.children}
      </div>
    );
  }
}

export default ContainerComponent;

问题:children prop的propType应该是什么?

当我将其设置为 object 时,当我将组件与多个 children:

一起使用时,它会失败
<ContainerComponent>
  <div>1</div>
  <div>2</div>
</ContainerComponent>

Warning: Failed prop type: Invalid prop children of type array supplied to ContainerComponent, expected object.

如果我将它设置为一个数组,如果我只给它一个child,它就会失败,即:

<ContainerComponent>
  <div>1</div>
</ContainerComponent>

Warning: Failed prop type: Invalid prop children of type object supplied to ContainerComponent, expected array.

请指教,我是不是应该为 children 元素做一个 propTypes 检查?

使用 oneOfTypePropTypes.node

尝试类似的操作
import PropTypes from 'prop-types'

...

static propTypes = {
    children: PropTypes.oneOfType([
        PropTypes.arrayOf(PropTypes.node),
        PropTypes.node
    ]).isRequired
}

static propTypes = {
    children: PropTypes.node.isRequired,
}

尝试自定义 propTypes :

 const  childrenPropTypeLogic = (props, propName, componentName) => {
          const prop = props[propName];
          return React.Children
                   .toArray(prop)
                   .find(child => child.type !== 'div') && new Error(`${componentName} only accepts "div" elements`);
 };


static propTypes = {

   children : childrenPropTypeLogic

}

Fiddle

const {Component, PropTypes} = React;

 const  childrenPropTypeLogic = (props, propName, componentName) => {
             var error;
          var prop = props[propName];
    
          React.Children.forEach(prop, function (child) {
            if (child.type !== 'div') {
              error = new Error(
                '`' + componentName + '` only accepts children of type `div`.'
              );
            }
          });
    
          return error;
    };
    
  

class ContainerComponent extends Component {
  static propTypes = {
    children: childrenPropTypeLogic,
  }

  render() {
    return (
      <div>
        {this.props.children}
      </div>
    );
  }
}



class App extends Component {
   render(){
    return (
    <ContainerComponent>
        <div>1</div>
        <div>2</div>
      </ContainerComponent>
    )
   }
}

ReactDOM.render(<App /> , document.querySelector('section'))
<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>

<section />

对我来说,这取决于组件。如果您知道需要填充什么,那么您应该尝试使用以下方式专门指定或指定多种类型:

PropTypes.oneOfType 

如果你想引用 React 组件,那么你将寻找

PropTypes.element

虽然,

PropTypes.node

描述任何可以呈现的东西——字符串、数字、元素或这些东西的数组。如果这适合你,那么就是这样。

有了非常的泛型组件,谁可以有很多类型children,你也可以使用下面的。但是我不推荐它。正如下面的评论中所提到的,它确实在某种程度上破坏了使用 PropTypes 的意义,并且通常还有其他方法可以指定您的组件需要什么。还要记住,eslint 和 ts 可能(可能)对这种缺乏特异性不满意:

PropTypes.any

如果你想精确匹配一个组件类型,勾选这个

MenuPrimary.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.arrayOf(MenuPrimaryItem),
    PropTypes.objectOf(MenuPrimaryItem)
  ])
}

如果您想精确匹配某些组件类型,请选中此

const HeaderTypes = [
  PropTypes.objectOf(MenuPrimary),
  PropTypes.objectOf(UserInfo)
]

Header.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.arrayOf(PropTypes.oneOfType([...HeaderTypes])),
    ...HeaderTypes
  ])
}

这里的答案似乎并没有完全涵盖 children 的检查。 nodeobject 太宽容了,我想检查确切的元素。这是我最终使用的:

  • 使用oneOfType([])允许单个或数组children
  • 对children的单个和数组分别使用shapearrayOf(shape({}))
  • 对 child 元素本身使用 oneOf

最后是这样的:

import PropTypes from 'prop-types'
import MyComponent from './MyComponent'

children: PropTypes.oneOfType([
  PropTypes.shape({
    type: PropTypes.oneOf([MyComponent]),
  }),
  PropTypes.arrayOf(
    PropTypes.shape({
      type: PropTypes.oneOf([MyComponent]),
    })
  ),
]).isRequired

这个问题帮助我更清楚地解决了这个问题:https://github.com/facebook/react/issues/2979

The PropTypes documentation 有以下

// Anything that can be rendered: numbers, strings, elements or an array
// (or fragment) containing these types.
optionalNode: PropTypes.node,

因此,您可以使用 PropTypes.node 检查对象或对象数组

static propTypes = {
   children: PropTypes.node.isRequired,
}

示例:

import React from 'react';
import PropTypes from 'prop-types';

class MenuItem extends React.Component {
    render() {
        return (
            <li>
                <a href={this.props.href}>{this.props.children}</a>
            </li>
        );
    }
}

MenuItem.defaultProps = {
    href: "/",
    children: "Main page"
};

MenuItem.propTypes = {
    href: PropTypes.string.isRequired,
    children: PropTypes.string.isRequired
};

export default MenuItem;

图片:如果预期类型不同,会在控制台中显示错误

如果你想包含渲染道具组件:

  children: PropTypes.oneOfType([
    PropTypes.arrayOf(PropTypes.node),
    PropTypes.node,
    PropTypes.func
  ])

根据propTypes documentation element用于React元素,children是其中之一:

// A React element.
optionalElement: PropTypes.element,

然后可以和arrayOf

结合

Component.propTypes = { children: PropTypes.arrayOf(PropTypes.element).isRequired, };

那么至少需要一个children.