我有这个简单的React组件:
import {PropTypes} from 'react';
import Column from './Column';
export default function ColumnContainer({children}) {
return (
<div className="cr-column-container">{children}</div>
);
}
let ColumnType = PropTypes.instanceOf(Column);
ColumnContainer.propTypes = {
children: PropTypes.oneOfType([
ColumnType,
PropTypes.arrayOf(ColumnType),
]).isRequired,
};
我使用的是这样的:
render() {
return (
<ColumnContainer>
<Column>
*snip*
</Column>
</ColumnContainer>
);
}
但它失败的道具式验证:
Warning: Failed prop type: Invalid prop `children` supplied to `ColumnContainer`.
in ColumnContainer (created by ExampleContainer)
in ExampleContainer
为什么?我只在Column
内使用ColumnContainer
。 PropTypes.instanceOf(Column)
不能像我期望的那样工作吗?我假设如何指定ColumnContainer
只接受Column
类型的儿童?
答案 0 :(得分:1)
进行了一些挖掘,提出了基于josephmartin09's solution的辅助函数:
export function childrenOf(...types) {
let fieldType = PropTypes.shape({
type: PropTypes.oneOf(types),
});
return PropTypes.oneOfType([
fieldType,
PropTypes.arrayOf(fieldType),
]);
}
用法:
ColumnContainer.propTypes = {
children: childrenOf(Column).isRequired,
};
它并不理想,因为它不支持像'div'
这样的原生DOM元素,并且错误信息毫无价值,但它现在还可以。
答案 1 :(得分:0)
我对childrenOf
进行了大修,以支持react-hot-loader 4.x:
import { areComponentsEqual } from 'react-hot-loader';
export function childrenOf(...types) {
return requirable((props, propName, componentName, location, propFullName) => {
const component = props[propName];
if(!location) {
location = 'prop';
}
if(!propFullName) {
propFullName = propName;
}
const check = c => types.some(type => areComponentsEqual(type,c.type));
const valid = Array.isArray(component) ? component.every(check) : check(component);
if(!valid) {
return new Error(
`Invalid ${location} \`${propFullName}\` supplied to \`${componentName}\`. Every element must be a <${types.map(t => getDisplayName(t)).join('|')}>.`
);
}
return null;
});
}
function requirable(predicate) {
const propType = (props, propName, ...rest) => {
// don't do any validation if empty
if(props[propName] === undefined) {
return null;
}
return predicate(props, propName, ...rest);
};
propType.isRequired = (props, propName, componentName, ...rest) => {
// warn if empty
if(props[propName] === undefined) {
return new Error(`Required prop \`${propName}\` was not specified in \`${componentName}\`.`);
}
return predicate(props, propName, componentName, ...rest);
};
return propType;
}
用法示例:
export function TBody({children, ...attrs}) {
return <tbody {...attrs}>{children}</tbody>;
}
TBody.propTypes = {
children: WxTypes.childrenOf(TRow),
};