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


265

给定一个呈现其子级的简单组件:

class ContainerComponent extends Component {
  static propTypes = {
    children: PropTypes.object.isRequired,
  }

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

export default ContainerComponent;

问题:孩子道具的propType应该是什么?

当我将其设置为对象时,当我将组件与多个子级一起使用时,它将失败:

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

警告:无法道具类型:无效的支柱children型的array 供给ContainerComponent,预计object

如果将其设置为数组,则如果我只给它一个孩子,它将失败:

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

警告:prop类型失败:提供给ContainerComponent的对象类型无效的prop子代,预期数组。

请告知,我是否应该不麻烦对子元素进行propTypes检查?


您可能想要node
lux


2
请参阅下面的我的答案,其中描述了更多选项,但是,如果您要查找子组件,则为PropTypes.element。PropTypes.node描述了可以渲染的任何东西-字符串,数字,元素或这些东西的数组。如果这适合您,那么这就是方法。
ggilberth

Answers:


369

尝试使用oneOfType或类似的方式PropTypes.node

import PropTypes from 'prop-types'

...

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

要么

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

1
不幸的是失败,并在独生子女的情况下相同的错误:“警告:无法道具类型:无效的支柱children型的object......预计的数组。”
d3ming

25
可行!最简单的解决方案是children: PropTypes.node,适用于两种情况。感谢您的建议=)
d3ming

6
唯一可以使该答案更清晰的是,如果您包含与@ggilberth的答案类似的注释,以说明React.PropTypes.node描述了任何可渲染对象。
theotherjim

只需数组PropTypes.node。处理以下更正:无,字符串,单个元素,几个元素,片段,组件。
Dima Tisnek

38

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

PropTypes.oneOfType 

但是,我最发现的是,拥有更多可以包含多种类型子项的通用组件,我很乐于使用:

PropTypes.any

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

PropTypes.element

虽然,

PropTypes.node

描述可以渲染的任何东西-字符串,数字,元素或这些东西的数组。如果这适合您,那么这就是方法。


7
Proptypes.any是太普通的类型。埃斯林特对此不满意。
Alex Shwarc

20

PropTypes文档具有以下内容

// 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,
}

12

这里的答案似乎并不能完全涵盖对孩子的确切检查。node而且object太宽容了,我想检查确切的元素。这是我最终使用的内容:

  • 使用oneOfType([])允许单个或儿童阵列
  • 分别用于shape和分别arrayOf(shape({}))用于单个和一组子代
  • 使用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


5

如果要完全匹配组件类型,请选中此

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

2

尝试自定义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

}

小提琴


0

例:

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;

图片:如果期望的类型不同,则会显示控制台错误

图片:如果期望的类型不同,则会显示控制台错误

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.