如何在 React 组件 PropTypes 中定义替代要求 属性?

How to define alternative required property in a React component PropTypes?

这是用例:组件 TableGroup 应该要求用户指定 data 属性 这是要在 table 中呈现的对象数组 requestDataUrl 属性 组件将从哪里获取该对象数组。简而言之,这两个属性中的一个是必需的,但不是两个都需要。我怎样才能在下面的 component.propTypes 对象中实现它?

TableGroup.propTypes = {
  fieldNames: React.PropTypes.array.isRequired,
  dataFields: React.PropTypes.array.isRequired,
  uniqueField: React.PropTypes.string.isRequired,
  data: React.PropTypes.array,
  requestUrlSource: http://someurl/api/resource
}

要达到预期结果,请使用以下选项

function dataOrRequest(props, propName, componentName) {
  return  (!props.hasOwnProperty('data') && 
             !props.hasOwnProperty('requestUrlSource')) 
            && new Error(`Either "data" or "requestUrlSource" is required`);
}


TableGroup.propTypes = {
  fieldNames: React.PropTypes.array.isRequired,
  dataFields: React.PropTypes.array.isRequired,
  uniqueField: React.PropTypes.string.isRequired,
  data: dataOrRequest,
  requestUrlSource: dataOrRequest
}

根据 React 的 doc,我认为 customProp 应该非常适合你。

dataOrRequest: function(props, propName, componentName) {
  function checkDataOrRequest() {
    return  (!props.hasOwnProperty('data')
      && !props.hasOwnProperty('requestUrlSource')) 
      && new Error(`Either "data" or "requestUrlSource" is required`);
  }

  function checkTypes() {
    if ((propName === 'data' && props.constructor !== Array) ||
        (propName === 'requestUrlSource' && props.constructor !== String)) {
      return new Error(
        'Invalid prop `' + propName + '` supplied to' +
        ' `' + componentName + '`. Validation failed.'
      );
    }

    return false;
  }

  return checkDataOrRequest() && checkTypes();  
}

声明自定义验证 fn 后,现在您可以在

中使用它
TableGroup.propTypes = {
  data: dataOrRequest,
  requestUrlSource: dataOrRequest
}

我为此编写了一个 NPM 模块:https://www.npmjs.com/package/react-either-property

代码维护类型检查选项,提供 EitherOptional 和 EitherRequired 策略——它支持在一个 props 定义中组合多种用法。

注意:自定义规则的 属性 名称是一次性的,其作为实际 属性 的用法未定义。

import { EitherOptional, EitherRequired } from 'react-either-property';

    [ module code goes here] 

ComponentSeven.propTypes = {
  east: PropTypes.number,
  west: PropTypes.number,
  north: PropTypes.number,
  south: PropTypes.number,
  ignored: EitherOptional('north', 'south'),
  undefined: EitherRequired('north', 'south'),
};

使用isRequiredIf.

4 年前@evcohen 的 PR 添加了 isRequiredIf 到 PropTypes 库。不幸的是,即使在那个时候他们也将 PropTypes 库置于维护模式并且不会将其合并。

company I work for 仍然使用 PropTypes,因此我们分叉了 PropTypes 库的 master 分支,并在其中添加了此功能。

所以现在你可以这样做:

data:             PropTypes.array.isRequiredIf( props => !props.requestUrlSource ),
requestUrlSource: PropTypes.string.isRequiredIf( props => !props.data )

超级干净和简约。

通过使用以下内容更新 package.json,您可以在自己的项目中随意使用 our fork

"prop-types": "github:cntral/prop-types#isRequiredIf"

注意:它不接受布尔参数,只有一个传递道具的函数需要return一个布尔值。