Javascript 是否可以为有条件要求的对象数组编写自定义的prop类型验证器,而不丢失对象验证?

Javascript 是否可以为有条件要求的对象数组编写自定义的prop类型验证器,而不丢失对象验证?,javascript,reactjs,react-proptypes,Javascript,Reactjs,React Proptypes,我在react组件中使用道具类型。该组件有一个propdata,它应该是这样一个对象数组:[{value:'some string',id:123}]。我想添加一个自定义道具类型函数,如果props.useCustomSuggestions为false,则需要数据。我试过这样的方法: data: (props) => { if (!props.useCustomSuggestions && !props.data) { return new Error('Dat

我在react组件中使用道具类型。该组件有一个prop
data
,它应该是这样一个对象数组:
[{value:'some string',id:123}]
。我想添加一个自定义道具类型函数,如果
props.useCustomSuggestions
false
,则需要
数据。我试过这样的方法:

data: (props) => {
  if (!props.useCustomSuggestions && !props.data) {
    return new Error('Data must be provided to use default suggestions');
  } else if (props.data && typeof props.data !== 'object') {
    return new Error(
      'Data must be an array',
    );
  }
};
我相信这可以验证当
props.useCustomSuggestions
false
时是否需要数组,但它不会检查
数据中的对象是否正确格式化。是否有另一种写入方法来验证数组是否由属性
value
为string类型且属性
id
为number类型的对象组成


我认为react中的文档可能是解决方案,但它没有传递整个props对象,因此我无法根据
useCustomSuggestions
的值有条件地生成
数据,或对以下代码的反馈,请仍发表评论或发布您自己的答案

data: (props) => {
  if (!props.useCustomSuggestions && !props.data) {
    return new Error('Data must be provided to use default suggestions');
  } else if (props.data && !Array.isArray(props.suggestions)) {
    return new Error('Data must be an array');
  } else if (props.data.length > 0) {
    for (let i = 0; i < props.data.length; i += 1) {
      if (!props.data[i].value || !props.data[i].id) {
        return new Error(
          'Objects in data must include properties "value" and "id"',
        );
      } else if (
        typeof props.data[i].value !== 'string' ||
        typeof props.data[i].id !== 'number'
      ) {
        return new Error(
          'Objects in data array must have property "value" of type string, and "id" of type number',
        );
      }
    }
  }
},

数据:(道具)=>{
如果(!props.useCustomSuggestions&!props.data){
返回新错误(“必须提供数据才能使用默认建议”);
}else if(props.data&&!Array.isArray(props.suggestions)){
返回新错误('数据必须是数组');
}否则如果(props.data.length>0){
for(设i=0;i
有一种特殊的方法可以重用它们的检查逻辑:
PropTypes.checkPropTypes()

PS出于未知原因codesandbox有时会运行
propTypes
check,有时会默默地跳过它,所以我的代码示例不是100%有效。但我已经用
字符串
/
数字
检查了这种方法——就在我试图将其应用于
数组
/
形状
时,它开始变得奇怪


也许您可以将公共部分(
shape
的内部)移动到interm变量以减少代码重复,但正如我所说的,您无法确保这一点。

试想一下:提取列表项的组件并检查其中的shape prop type可能是有意义的。更具可读性->更易于维护。@skyboyer我一直在想一个好方法来做到这一点。所讨论的组件是附加到文本输入的建议下拉列表。如果
useCustomSuggestions
为false,则我们处理其数据的所有过滤逻辑,以显示最相关的建议/返回过滤后的数据。如果这是真的,他们使用自己的规则处理所有过滤,然后将建议传递给我们。我能想到的消除条件道具的唯一选择是将这些选项变成两个完全不同的组件。我无法确定这是否是一个好的解决方案,因为从视觉上看,它们完全相同。没有更多细节(特别是关于“在其端处理所有过滤”的含义)这个问题太笼统了,没有唯一的解决办法。但是对于这两个案例和道具来说,结构和UI外观都是一样的,对吗?只是应用了不同的过滤规则,对吗?对,UI是相同的,但过滤会不同。这方面的主要用例是,如果数据来自分页的API,那么用户需要调用API以获得正确的建议。我认识到这可能超出了原始问题的范围,因此可能需要一个新问题。如果我发布一个,我会在这里的评论中链接它。谢谢你的帮助!
data: (props, propName, componentName) => {
  if (props.useCustomSuggestion) {  // data should be validated but is optional
    PropTypes.checkPropTypes({ 
        [propName]: PropTypes.arrayOf(
          PropTypes.shape({
            value: PropTypes.string.isRequired,
            id: PropTypes.number.isRequired
         }) 
        ) 
      }, 
      props, 
      propName, 
      componentName
    );
  } else { // data is required
    PropTypes.checkPropTypes({ 
        [propName]: PropTypes.arrayOf(
          PropTypes.shape({
            value: PropTypes.string.isRequired,
            id: PropTypes.number.isRequired
         }) 
        ).isRequired
      }, 
      props, 
      propName, 
      componentName
    );
  }
}