用形状反应原型数组


244

是否存在使用原型的内置方法,以确保传递给组件的对象数组实际上是特定形状的对象数组?

也许是这样的?

annotationRanges: PropTypes.array(PropTypes.shape({
    start: PropTypes.number.isRequired,
    end: PropTypes.number.isRequired,
})),

我在这里想念什么超级明显吗?似乎将受到高度追捧。

Answers:


370

您可以将React.PropTypes.shape()以下参数用作参数React.PropTypes.arrayOf()

// an array of a particular shape.
ReactComponent.propTypes = {
   arrayWithShape: React.PropTypes.arrayOf(React.PropTypes.shape({
     color: React.PropTypes.string.isRequired,
     fontSize: React.PropTypes.number.isRequired,
   })).isRequired,
}

请参阅文档的“ 验证属性”部分。

更新

从开始react v15.5React.PropTypes不推荐使用using ,而prop-types应使用独立软件包:

// an array of a particular shape.
import PropTypes from 'prop-types'; // ES6 
var PropTypes = require('prop-types'); // ES5 with npm
ReactComponent.propTypes = {
   arrayWithShape: PropTypes.arrayOf(PropTypes.shape({
     color: PropTypes.string.isRequired,
     fontSize: PropTypes.number.isRequired,
   })).isRequired,
}

17
值得指出.isRequired对的每个属性的使用React.PropTypes.shape。我到达这里是因为我错误地认为通过使用.isRequiredon React.PropTypes.arrayOf,我不需要在里面使用它。为了获得完整的覆盖范围验证,实际上我最终也直接将其应用了React.PropTypes.shape
gfullam '16

1
是的,我所做的事情比您完全相同,但是可以只根据需要标记您想要的键,这将更加强大。对我而言,显式总是比隐式好。
皮埃尔·克劳兰西

这个例子不会对我正确地验证失败。如果if arrayWithShape为[](空数组),则不会失败。如果arrayWithShape是{}(一个对象),则它确实会失败。如果 arrayWithShape[{dumb: 'something'}](没有正确道具的数组),它将失败。如果它arrayWithShape是一个空数组,我需要它使验证失败。我只希望它通过的对象是带有props color和的对象的非空数组时通过fontsize。我想念什么?
sdc

50

是的,您需要使用PropTypes.arrayOf而不是PropTypes.array在代码中,您可以执行以下操作:

import PropTypes from 'prop-types';

MyComponent.propTypes = {
  annotationRanges: PropTypes.arrayOf(
    PropTypes.shape({
      start: PropTypes.string.isRequired,
      end: PropTypes.number.isRequired
    }).isRequired
  ).isRequired
}

此外如需详细了解proptypes,访问类型检查有了PropTypes 这里


3
将.isRequired添加到PropTypes.shape对象的原因是什么?
makovkastar

@makovkastar因为没有它,[undefined]它将通过验证
user123


6

有一个ES6速记导入,您可以参考。更具可读性和易于键入。

import React, { Component } from 'react';
import { arrayOf, shape, number } from 'prop-types';

class ExampleComponent extends Component {
  static propTypes = {
    annotationRanges: arrayOf(shape({
      start: number,
      end: number,
    })).isRequired,
  }

  static defaultProps = {
     annotationRanges: [],
  }
}

1
请查看我如何写一个好的答案。不建议使用仅代码的答案,因为它们没有解释如何解决问题中的问题。您应该更新您的答案,以解释此功能以及在此问题已获好评的答案上如何改进。
FluffyKitten

1

如果我要为一个特定形状多次定义相同的原型,我喜欢将其抽象到一个原型文件中,这样,如果对象的形状发生变化,我只需要在一个地方更改代码即可。它有助于使代码库变干一点。

例:

// Inside my proptypes.js file
import PT from 'prop-types';

export const product = {
  id: PT.number.isRequired,
  title: PT.string.isRequired,
  sku: PT.string.isRequired,
  description: PT.string.isRequired,
};


// Inside my component file
import PT from 'prop-types';
import { product } from './proptypes;


List.propTypes = {
  productList: PT.arrayOf(product)
}

0

这也是我防止空数组的解决方案:

import React, { Component } from 'react';
import { arrayOf, shape, string, number } from 'prop-types';

ReactComponent.propTypes = {
  arrayWithShape: (props, propName, componentName) => {
    const arrayWithShape = props[propName]
    PropTypes.checkPropTypes({ arrayWithShape:
        arrayOf(
          shape({
            color: string.isRequired,
            fontSize: number.isRequired,
          }).isRequired
      ).isRequired
    }, {arrayWithShape}, 'prop', componentName);
    if(arrayWithShape.length < 1){
      return new Error(`${propName} is empty`)
    }
  }
}
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.