React PropTypes如何要求数组至少包含一个元素?
优雅实现非空数组的PropTypes校验
你说得太对了——手写全量的自定义校验确实会随着对象结构变复杂而变得臃肿,咱们可以把PropTypes的内置校验逻辑和自定义的非空判断结合起来,既复用现有能力,又满足非空要求,代码会清爽很多!
第一步:复用内置的Shape校验
先把数组元素的结构校验单独抽出来,这样不管在哪里用都能复用,也方便后续修改:
// 定义元素的结构校验器 const ItemShape = PropTypes.shape({ bar: PropTypes.string.isRequired, baz: PropTypes.number.isRequired, }).isRequired;
第二步:组合内置校验与非空判断
接下来写自定义校验函数,先调用PropTypes原生的arrayOf校验确保数组类型和元素格式正确,再额外添加非空判断:
MyComponent.propTypes = { foo: function(props, propName, componentName) { // 先让PropTypes帮我们校验数组类型和元素结构 const builtInValidationError = PropTypes.arrayOf(ItemShape).isRequired( props, propName, componentName ); // 如果内置校验出错,直接返回错误信息 if (builtInValidationError) { return builtInValidationError; } // 额外校验数组非空 const value = props[propName]; if (value.length === 0) { return new Error( `Invalid prop \`${propName}\` supplied to \`${componentName}\`. Expected non-empty array, got empty array.` ); } } };
进阶:封装通用的非空数组校验器
如果你的项目里多个地方都需要非空数组校验,可以把这个逻辑封装成一个通用的高阶函数,以后直接调用就行:
// 通用非空数组校验生成器 const nonEmptyArrayOf = (elementValidator) => { return function(props, propName, componentName) { // 复用内置数组+元素校验 const arrayValidationError = PropTypes.arrayOf(elementValidator).isRequired( props, propName, componentName ); if (arrayValidationError) { return arrayValidationError; } // 非空判断 const value = props[propName]; if (value.length === 0) { return new Error( `Invalid prop \`${propName}\` supplied to \`${componentName}\`. Expected non-empty array, got empty array.` ); } }; }; // 使用时就超级简洁了 MyComponent.propTypes = { foo: nonEmptyArrayOf(ItemShape) };
这种方式的好处在于:
- 完全复用PropTypes的内置校验逻辑,不用自己手写繁琐的类型判断,减少出错概率
- 代码结构清晰,元素结构和非空逻辑分离,维护起来更轻松
- 通用函数可以全局复用,避免重复造轮子
内容的提问来源于stack exchange,提问作者PullJosh
相关产品推荐
相关产品推荐

