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

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

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

export default ContainerComponent;

问:儿童道具的道具类型应该是什么?

当我将它设置为一个对象时,当我使用有多个子组件时,它会失败:

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

警告:失败的道具类型:类型数组的无效道具子元素 提供给ContainerComponent,期望对象。

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

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

警告:失败的道具类型:类型对象的无效道具子 提供给ContainerComponent,期望数组。

请建议,我不应该打扰做一个propTypes检查子元素?


当前回答

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

}

小提琴

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

其他回答

尝试使用oneOfType或PropTypes.node这样做

import PropTypes from 'prop-types'

...

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

or

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

}

小提琴

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

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

对于非常通用的组件,可以有许多类型的子组件,您还可以使用下面的方法。但是我不建议这样做。正如下面的评论中提到的,它确实在某种程度上破坏了使用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
  ])
}

这里的答案似乎并没有完全涵盖对孩子们的检查。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