Tengo un componente <Button>.
Si el componente no tiene this.props.children, quiero establecer el accesorio ariaLabel como isRequired, de lo contrario, puede ser opcional. ¿Cómo puedo hacer eso?

ariaLabel accesorio no requerido:

<Button>Add to bag</Button>

Se debe requerir ariaLabel accesorio:

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

si this.props.children y this.props.ariaLabel están vacíos, arroja un error que dice que this.props.ariaLabel es isRequired

<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 */
};

Gracias

46
sandrina-p 17 feb. 2017 a las 16:35

4 respuestas

La mejor respuesta

No necesita otra biblioteca, 'prop-types' proporciona esto de forma inmediata. Consulte https://facebook.github.io/react/docs/typechecking- with-proptypes.html

Ejemplo:

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!');
        }
    },

}
103
Lucas P. 25 jul. 2019 a las 16:48

Creo que estas soluciones son un poco exageradas en parte porque la pregunta lo solicita.

No creo que deba complicar su código con este tipo de situaciones, debe intentar mantener su código limpio. Puede hacer esto en render en lugar de en propsTypes

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

...
-2
Val 4 nov. 2019 a las 11:22

Para agregar a la respuesta anterior de @ chickenchilli, puede resumir esto en una función auxiliar más útil como esta:

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"),
};
8
coconup 26 jun. 2018 a las 17:12

Esto puede ser exactamente lo que necesita: https://github.com/thejameskyle/react-required-if

En su caso, sus propTypes serían:

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 */
};
16
Kelvin De Moya 17 feb. 2017 a las 16:00