【问题标题】:ReactJs: What should the PropTypes be for this.props.children?ReactJs:this.props.children 的 PropTypes 应该是什么?
【发布时间】:2017-06-26 15:01:10
【问题描述】:

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

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

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

export default ContainerComponent;

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

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

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

警告:失败的道具类型:无效的道具children 类型为array 提供给ContainerComponent,预期object

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

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

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

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

【问题讨论】:

  • 你可能想要node
  • 请看下面我的回答,其中描述了更多选项,但是,如果您正在寻找组件子组件,那么它就是 PropTypes.element。 PropTypes.node 描述了任何可以渲染的东西——字符串、数字、元素或这些东西的数组。如果这适合你,那么这就是方式。

标签: reactjs jsx react-proptypes


【解决方案1】:

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

【讨论】:

  • 不幸的是,它在单个子案例中失败并出现相同的错误:“警告:失败的道具类型:无效的道具children 类型为object...预期一个数组。”
  • 成功了!最简单的解决方案是children: PropTypes.node,它适用于这两种情况。感谢您的建议 =)
  • 唯一能让这个答案更清楚的是,如果你包含一个类似于@ggilberth 的答案的注释来解释React.PropTypes.node 描述了任何可渲染对象。
  • 不需要数组,只需要PropTypes.node。它处理以下更正:无、字符串、单个元素、多个元素、片段、组件。
  • 我需要把这个答案挂在我房间墙上的某个地方。我一遍又一遍地回到这里。 :)
【解决方案2】:

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

PropTypes.oneOfType 

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

PropTypes.element

虽然,

PropTypes.node

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

使用 非常 通用组件,可以有多种类型的子组件,您也可以使用以下内容 - 尽管请记住 eslint 和 ts 可能不满意这种缺乏特异性:

PropTypes.any

【讨论】:

  • Proptypes.any 是太常见的类型。 Eslint 对此并不满意。
  • Proptypes.any 也表示object,如果您传递object,应用程序可能会崩溃。
  • 如果你打算使用any,你应该完全节省使用propTypes的时间。
【解决方案3】:

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】:

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

    【讨论】:

      【解决方案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
        ])
      }
      

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

          【解决方案7】:

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

          【讨论】:

            【解决方案8】:

            例子:

            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;
            

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2017-02-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-08-31
              相关资源
              最近更新 更多