React props - 如果另一个prop为null / empty,则在prop上设置isRequired

时间:2017-02-17 13:35:30

标签: javascript reactjs wai-aria

我有一个组件<Button> 如果组件没有this.props.children,我想将道具ariaLabel设置为isRequired,否则可以是可选的。我该怎么做?

ariaLabel道具不需要:

<Button>Add to bag</Button>
必须要求

ariaLabel道具

<Button ariaLabel="Add to bag" icon={ favorite } />

如果this.props.childrenthis.props.ariaLabel为空,则会发出错误消息,指出this.props.ariaLabelisRequired

<Button icon={ favorite } />

propTypes:

Button.propTypes = {
    /** icon inside Button. */
    icon: React.PropTypes.object,
    /** Content inside button */
    children: React.PropTypes.node,
    /** Aria-label to screen readers */
    ariaLabel: React.PropTypes.string, /*isRequired if children is empty */
};

由于

5 个答案:

答案 0 :(得分:79)

你不需要另一个图书馆,&#39; prop-types&#39;开箱即用。 见https://facebook.github.io/react/docs/typechecking-with-proptypes.html

示例:

import PropTypes from 'prop-types';

//.......    

ExampleComponent.propTypes = {
    showDelete: PropTypes.bool,
    handleDelete: function(props, propName, componentName) {
        if ((props['showDelete'] == true && (props[propName] == undefined || typeof(props[propName]) != 'function'))) {
            return new Error(
                'Please provide a handleDelete function!';
            );
        }
    },

}

答案 1 :(得分:14)

这可能正是您所需要的:https://github.com/thejameskyle/react-required-if

在您的情况下,您的propTypes将是:

import requiredIf from 'react-required-if';

Button.propTypes = {
    /** icon inside Button. */
    icon: React.PropTypes.object,
    /** Content inside button */
    children: React.PropTypes.node,
    /** Aria-label to screen readers */
    ariaLabel: requiredIf(React.PropTypes.string, props => !props.children), /*isRequired if children is empty */
};

答案 2 :(得分:4)

要添加到上述@chickenchilli的答案中,您可以将其抽象为更方便的辅助函数,如下所示:

conditionalPropType.js

export default function conditionalPropType(condition, message) {
  if(typeof condition !== 'function') throw "Wrong argument type 'condition' supplied to 'conditionalPropType'";
  return function(props, propName, componentName) {
    if (condition(props, propName, componentName)) {
      return new Error(`Invalid prop '${propName}' '${props[propName]}' supplied to '${componentName}'. ${message}`);
    }
  }
}

MyComponent.js

import PropTypes from 'prop-types';
import conditionalPropType from './conditionalPropType';

[...]

MyComponent.propTypes = {
  conditionProp: PropTypes.bool,
  dependentProp: conditionalPropType(props => (props.condition && typeof(props.someProp) !== 'boolean'), "'dependentProp' must be boolean if 'conditionProp' is true"),
};

答案 3 :(得分:1)

使用isRequiredIf

4年前有一个PR,它向PropTypes库中添加了isRequiredIf。不幸的是,即使在那时,他们仍将PropTypes库置于维护模式,并且无法将其合并。

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

现在您可以执行以下操作:

ariaLabel: PropTypes.string.isRequiredIf( props => props.children )

超级干净,最小。

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

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

注意:它不需要布尔参数,只需要传递道具并需要返回布尔值的函数即可。

答案 4 :(得分:0)

我认为这些解决方案有些过头了,因为这个问题正在要求这样做。

我不认为您应该使代码复杂化,而应该保持代码干净。您可以在render而不是propsTypes

上执行此操作
...
render(){
  if(!this.children || !this.ariaLabel) { 
     throw "You need children or ariaLabel"; 
     return;
  }
  //rest of the code.
}

...