react类型检查PropTypes

PropTypes 是一个在 编码 阶段提供类型检查的方案

1. PropTypes 使用

npm地址:https://www.npmjs.com/package/prop-types

安装:

plaintext
1
npm install --save prop-types

导入包:

js
1
2
import PropTypes from 'prop-types'; // ES6
var PropTypes = require('prop-types'); // ES5 with npm

使用:

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React from 'react';
import PropTypes from 'prop-types';

class MyComponent extends React.Component {
render() {
// ... do things with the props
}
}

// 使用
MyComponent.propTypes = {
name: PropTypes.string, // 不带isRequired一般需要给一个默认值
history: PropTypes.object.isRequired, // 可以不需要默认值
}

// 给一个默认值
MyComponent..defaultProps = {
name: 'jack'
}

纯函数的用法:

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
import PropTypes from 'prop-types';

const FundManagement = props => {
const {children} = props;
return (
<div className="statistics">
{children}
</div>
);
};
FundManagement.propTypes = {
children: PropTypes.element.isRequired,
};

2. 不同类型的验证

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// 数组、布尔、函数、数字、对象、字符串、symbol
MyComponent.propTypes = {
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,

// 任何东西都可以被渲染:numbers, strings, elements,或者是包含这些类型的数组(或者是片段)。
optionalNode: PropTypes.node,

// 一个 React 元素。
optionalElement: PropTypes.element,
// 一个react元素类型
optionalElementType: PropTypes.elementType,

// 你也可以声明一个 prop 是类的一个实例。
// 使用 JS 的 instanceof 运算符。
optionalMessage: PropTypes.instanceOf(Message),

// 你可以声明 prop 是特定的值,类似于枚举
optionalEnum: PropTypes.oneOf(['News', 'Photos']),

// 一个对象可以是多种类型其中之一
optionalUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.instanceOf(Message)
]),

// 一个某种类型的数组
optionalArrayOf: PropTypes.arrayOf(PropTypes.number),

// 属性值为某种类型的对象
optionalObjectOf: PropTypes.objectOf(PropTypes.number),

// 一个特定形式的对象
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number
}),

// 你可以使用 `isRequired' 链接上述任何一个,以确保在没有提供 prop 的情况下显示警告。
requiredFunc: PropTypes.func.isRequired,

// 任何数据类型的值
requiredAny: PropTypes.any.isRequired,

// 你也可以声明自定义的验证器。如果验证失败返回 Error 对象。不要使用 `console.warn` 或者 throw ,
// 因为这不会在 `oneOfType` 类型的验证器中起作用。
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error(
'Invalid prop `' + propName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
},

// 也可以声明`arrayOf`和`objectOf`类型的验证器,如果验证失败需要返回Error对象。
// 会在数组或者对象的每一个元素上调用验证器。验证器的前两个参数分别是数组或者对象本身,
// 以及当前元素的键值。
customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
if (!/matchme/.test(propValue[key])) {
return new Error(
'Invalid prop `' + propFullName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
})
};

3. 为什么要类型检查

下面内容转载自:https://segmentfault.com/a/1190000015071373

我们先来看一份 rollbar 公司对 1000+ 项目的错误回收分析 top10

大部分都是类型错误。

比如定义 let prodList = [] , 你代码中 prodList.push(...)

但是初始的时候被设置 prodList = 123 而且没有任何提示, 那运行 push(...) 肯定要报未知方法的错误

这种问题在自由的 JavaScript 世界很普遍,如果在 编译 运行 两个阶段都没提示的话,排错是很麻烦的,全靠经验和对业务的熟悉 (陈年老项目又没文档简直是地狱)

所以我们要把问题消灭在萌芽中,就是申明对象的时候同时把类型也定义掉了, react 的自带方案是 PropTypes 组件

4. 常见报错(类型检查)

类型不一致报错:

jsx
1
2
3
4
5
6
7
8
9
10
11
12
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>
}
}
Greeting.propTypes = {
name: PropTypes.string
}

<div>
<Greeting name={123} />
</div>

限制单个子代:

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
// 组件
const OnlyOneChild = props => {
const children = props.children
return <div>{children}</div>
}
OnlyOneChild.propTypes = {
children: PropTypes.element.isRequired
}
// 容器
<OnlyOneChild>
<h3>第一个子节点</h3>
<h3>第二个子节点</h3>
</OnlyOneChild>

参考资料

prop-types NPM

React 快速上手 - 10 类型检查 PropTypes segmentfault