首页 文章

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

提问于
浏览
117

给出一个渲染其子代的简单组件:

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

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

export default ContainerComponent;

Question: What should the propType of the children prop be?

当我将其设置为对象时,当我使用具有多个子元素的组件时,它会失败:

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

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

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

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

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

请指教,如果我不打算对儿童元素进行propTypes检查?

6 回答

  • 16

    利用 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,
    }
    
  • 4

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

    PropTypes.oneOfType
    

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

    PropTypes.any
    

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

    PropTypes.element
    

    虽然,

    PropTypes.node
    

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

  • 2

    这里的答案似乎并不完全涵盖检查孩子 . 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

  • 163

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

    如果要精确匹配组件类型,请选中此选项

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

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

相关问题