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

时间:2017-02-08 20:00:19

标签: reactjs jsx react-proptypes

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

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>
  

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

请注意,如果我不打算为子元素执行propTypes检查?

8 个答案:

答案 0 :(得分:241)

使用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,
}

答案 1 :(得分:23)

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

PropTypes.oneOfType 

但是我发现,通过更多通用组件可以拥有多种类型的孩子,我很乐意使用:

PropTypes.any

如果您想参考React组件,那么您将寻找

PropTypes.element

虽然

PropTypes.node

描述了可以呈现的任何内容 - 字符串,数字,元素或这些内容的数组。如果这适合你,那么就是这样。

答案 2 :(得分:6)

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

答案 3 :(得分:4)

这里的答案似乎并不完全涵盖了对孩子的检查。 nodeobject过于宽松,我想查看确切的元素。以下是我最终使用的内容:

  • 使用oneOfType([])允许单个或多个孩子
  • 分别对单个和一系列子项使用shapearrayOf(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

答案 4 :(得分:2)

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

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

答案 5 :(得分:1)

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

答案 6 :(得分: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;

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

Picture: Shows you error in console if the expected type is different

答案 7 :(得分:0)

如果要包括渲染道具组件:

from apscheduler.schedulers.background import BlockingScheduler
def print_t():
  pass

sched = BlockingScheduler()
sched.add_job(print_t, 'interval', seconds =60) #will do the print_t work for every 60 seconds

sched.start()