一、概述
props是React组件接收的外部参数,相当于是组件暴露给外部的接口。PropTypes的作用更多的是一种文档性质的限制,通过给每个props属性设置对应的PropTypes来提示开发者和使用者组件对外暴露的接口限制。本文同时介绍了defaultProps的使用方法。
二、PropTypes
从React 15.5版本开始,PropTypes由prop-types三方件提供。使用命令npm i -D prop-types安装。React 15.5之前的版本PropTypes由react提供,不需要安装。
(一)基本使用方法
export const SMALL = 'small';
export const NORMAL = 'normal';
export const LARGE = 'large';
const SIZE = {
small: { width: '32px', height: '16px' },
normal: { width: '64px', height: '32px' },
large: { width: '96px', height: '64px' },
};
export const Button = ({ text, size }) => (
<button style={SIZE[size] || SIZE[SMALL]}>{text}</button>
);
以上代码实现了一个按钮,接收两个参数:text和size,text用来定义按钮的文本,size用来定义按钮的大小,提供了三种可选的大小。从它们的含义上看,text要求是字符串,size要求是组件提供的枚举值,但是如果不按这个要求传参,代码也不会有任何形式的报错。这样对于不熟悉这个组件的开发者来说不太友好,也不利于项目开发和维护。
用PropTypes对参数的类型加以限制:
import PropTypes from 'prop-types';
export const SMALL = 'small';
export const NORMAL = 'normal';
export const LARGE = 'large';
const SIZE = {
small: { width: '32px', height: '16px' },
normal: { width: '64px', height: '32px' },
large: { width: '96px', height: '64px' },
};
export const Button = ({ text, size }) => (
<button style={SIZE[size] || SIZE[SMALL]}>{text}</button>
);
Button.propTypes = {
/** 按钮文本 */
text: PropTypes.string,
/** 按钮大小 */
size: PropTypes.oneOf([SMALL, NORMAL, LARGE]),
};
这样如果在使用时没有按要求传参,比如size传错了,不是规定的枚举值之一:
import { Button } from './Button.jsx';
import './App.css';
function App() {
return (
<div className="App">
<Button text={'按钮'} size={1} />
</div>
);
}
export default App;
控制台会报错:
但是并不会影响代码的执行,也不会抛出异常,所以PropTypes的限制更多的是一种文档性质的提示。这类控制台提示只在开发模式下起作用,在项目最后以发布模式打包的时候不会把这个功能打包进去。
(二)PropTypes的类型
- 数组:PropTypes.array
- 布尔值:PropTypes.bool
- 函数:PropTypes.func
- 数值:PropTypes.number
- 对象:PropTypes.object
- 字符串:PropTypes.string
- symbol:PropTypes.symbol
- 任何可被渲染的元素:PropTypes.node
- 一个React元素:PropTypes.element
- 一个指定的React元素类型:PropTypes.elementType
- 一个指定类型的实例:PropTypes.instanceOf(Message)
- 枚举值:PropTypes.oneOf([‘News’, ‘Photos’])
- 指定类型中的任意一个类型实例:PropTypes.oneOfType([ PropTypes.string, PropTypes.number, PropTypes.instanceOf(Message) ])
- 由某一类型元素组成的数组:PropTypes.arrayOf(PropTypes.number)
- 由某一类型的值组成的对象:PropTypes.objectOf(PropTypes.number)
- 指定对象由特定的类型值组成:PropTypes.shape({ color: PropTypes.string, fontSize: PropTypes.number })
- 指定对象必须提供指定属性和指定类型:PropTypes.exact({ name: PropTypes.string, quantity: PropTypes.number })
- 在任何PropTypes属性后面加上isRequired可以使该属性未被提供时,打印警告信息:PropTypes.func.isRequired
三、defaultProps
defaultProps用于给props提供默认值,比如为Button的size属性设置一个默认值:
import PropTypes from 'prop-types';
export const SMALL = 'small';
export const NORMAL = 'normal';
export const LARGE = 'large';
const SIZE = {
small: { width: '32px', height: '16px' },
normal: { width: '64px', height: '32px' },
large: { width: '96px', height: '64px' },
};
export const Button = ({ text, size }) => (
<button style={SIZE[size] || SIZE[SMALL]}>{text}</button>
);
Button.defaultProps = {
size: NORMAL
};
Button.propTypes = {
/** 按钮文本 */
text: PropTypes.string,
/** 按钮大小 */
size: PropTypes.oneOf([SMALL, NORMAL, LARGE]),
};
这样当size未传参的时候Button也可以有默认的normal的大小。
四、defaultProps和PropTypes配合的注意事项
- 只能给没有标记PropTypes.isRequired的属性赋defaultProps,否则会导致isRequired的检查不生效。
- defaultProps的赋值也要满足对应PropTypes的要求,否则控制台也会提示不匹配,PropTypes的检查是在defaultProps赋值之后才做的。
- 对于PropTypes.isRequired的props,由于不能赋默认值,在代码中就要做非空判断。这样既能使isRequired检查生效,又不至于使代码抛异常。对于不是isRequired的属性,在设置了defaultProps之后,代码中就可以不做非空判断了。
五、参考资料
React关于PropTypes的官方文档:https://zh-hans.reactjs.org/docs/typechecking-with-proptypes.html