我需要制作至少一种所需的props:
MyComponent.propTypes = {
data: PropTypes.object,
url: PropTypes.string
};
因此,在上面的示例中,必须提供data
or 或url
prop。这里的用例是用户可以提供data
或url
。如果url
提供了 ,则组件将获取data
.
额外问题:我如何做至少一个props与只做一个props?
我需要制作至少一种所需的props:
MyComponent.propTypes = {
data: PropTypes.object,
url: PropTypes.string
};
因此,在上面的示例中,必须提供data
or 或url
prop。这里的用例是用户可以提供data
或url
。如果url
提供了 ,则组件将获取data
.
额外问题:我如何做至少一个props与只做一个props?
PropTypes 实际上可以将自定义函数作为参数,因此您可以执行以下操作:
MyComponent.propTypes = {
data: (props, propName, componentName) => {
if (!props.data && !props.url) {
return new Error(`One of props 'data' or 'url' was not specified in '${componentName}'.`);
}
},
url: (props, propName, componentName) => {
if (!props.data && !props.url) {
return new Error(`One of props 'url' or 'data' was not specified in '${componentName}'.`);
}
}
}
这允许客户错误消息。使用此方法时只能返回 null 或 Error
你可以在这里找到更多信息
https://facebook.github.io/react/docs/typechecking-with-proptypes.html#react.proptypes
来自react文档:
// You can also specify a custom validator. It should return an Error
// object if the validation fails. Don't `console.warn` or throw, as this
// won't work inside `oneOfType`.
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error(
'Invalid prop `' + propName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
},
@finalfreq 解决方案的更简洁版本:
const requiredPropsCheck = (props, propName, componentName) => {
if (!props.data && !props.url) {
return new Error(`One of 'data' or 'url' is required by '${componentName}' component.`)
}
}
Markdown.propTypes = {
data: requiredPropsCheck,
url: requiredPropsCheck,
}
添加在finalfreq 答案之上并与kousha评论相关。
我有一个需要图标或标题的按钮组件。确保至少有一个像上面的答案一样,之后检查它的类型可以像这样验证:
Button.propTypes = {
icon: (props, propName, componentName) => {
if (!props.icon && !props.title) {
return new Error(`One of props 'icon' or 'title' was not specified in '${componentName}'.`)
}
if (props.icon) {
PropTypes.checkPropTypes({
icon: PropTypes.string, // or any other PropTypes you want
},
{ icon: props.icon },
'prop',
'PrimaryButtonWithoutTheme')
}
return null
}
title: // same process
}
有关PropTypes.checkPropTypes
阅读此处的更多信息
我写了这个助手来以可重用的方式解决同样的问题。您可以像使用 propType 函数一样使用它:
MyComponent.propTypes = {
normalProp: PropType.string.isRequired,
foo: requireOneOf({
foo: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number
]),
bar: PropTypes.string,
}, true),
};
在这个例子中,它确保 foo 或 bar 之一在 MyComponent props中。如果您省略第二个参数,它将确保仅传递 foo 或 bar 之一。
/**
* Takes a propTypes object ensuring that at least one of the passed types
* exists on the component.
*
* Usage:
*
* MyComponent.propTypes = {
* normalProp: PropType.string.isRequired,
*
* foo: requireOneOf({
* foo: PropTypes.oneOfType([
* PropTypes.string,
* PropTypes.number
* ]),
* bar: PropTypes.string,
* }, true),
* };
*
* @param requiredProps object
* @param allowMultiple bool = false If true multiple props may be
* passed to the component
* @return {Function(props, propName, componentName, location)}
*/
export const requireOneOf = (requiredProps, allowMultiple = false) => {
return (props, propName, componentName, location) => {
let found = false;
for (let requiredPropName in requiredProps) {
if (requiredProps.hasOwnProperty(requiredPropName)) {
// Does the prop exist?
if (props[requiredPropName] !== undefined) {
if (!allowMultiple && found) {
return new Error(
`Props ${found} and ${requiredPropName} were both passed to ${componentName}`
);
}
const singleRequiredProp = {};
singleRequiredProp[requiredPropName] = requiredProps[requiredPropName];
const singleProp = {};
singleProp[requiredPropName] = props[requiredPropName];
// Does the prop match the type?
try {
PropTypes.checkPropTypes(singleRequiredProp, singleProp, location, componentName);
} catch (e) {
return e;
}
found = requiredPropName;
}
}
}
if (found === false) {
const propNames = Object.keys(requiredProps).join('", "');
return new Error(
`One of "${propNames}" is required in ${componentName}`
);
}
};
};