1.基本说明
PropTypes定义为组件类自身的属性,用以定义prop的类型。在开发模式下,当提供一个不合法的值作为prop时,控制台会出现警告;
在产品模式下,为了性能考虑应忽略propTypes
Prop types 是一个在运行时使用的新特性. 我们能够通过下面的方式在我们的团队里边使用.
2.版本更新
在15.5版本之后, 代替使用 PropTypes 直接从 React 对象这种导入方式, 安装一个新的包 prop-types 并且使用如下的方式进行导入:
// After (15.5) import React from 'react'; import PropTypes from 'prop-types'; class Component extends React.Component { render() { return <div>{this.props.text}</div>; } } Component.propTypes = { text: PropTypes.string.isRequired, };
如下代码,为之前的书写方式
// Before (15.4 and below) import React from 'react'; class Component extends React.Component { render() { return <div>{this.props.text}</div>; } } Component.propTypes = { text: React.PropTypes.string.isRequired, }
由于版本不一致,一般会导致如下错误:
Unhandled JS Exception: Cannot read property 'string' of undefined
只要按照版本对应起来使用就可以了
3.具体使用
静态属性,只能通过类名.属性名指定
class Greeting extends React.Component { render() { return ( <h1>Hello, {this.props.name}</h1> ); } } Greeting.propTypes = { // 静态属性,只能通过类名.属性名指定 name: PropTypes.string };
React.PropTypes输出一系列的验证器,用以确保你收到的数据是合法的。
下面是一个例子记录了不同的验证器;
MyComponent.propTypes = { // 可以声明prop是特定的JS基本类型 // 默认情况下这些prop都是可选的 optionalArray:PropTypes.array, optionalBool: PropTypes.bool, optionalFunc: PropTypes.func, optionalNumber: PropTypes.number, optionalObject: PropTypes.object, optionalString: PropTypes.string, optionalSymbol: PropTypes.symbol, // 任何可以被渲染的事物:numbers, strings, elements or an array // (or fragment) containing these types. optionalNode: PropTypes.node, // A React element. optionalElement: PropTypes.element, // 声明一个prop是某个类的实例,用到了JS的instanceof运算符 optionalMessage: PropTypes.instanceOf(Message), // 用enum来限制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对象 // 在array或者object中,验证器对于每个key都会被调用The first two // 验证器的前两个arguments是array或者object自身以及当前的key值 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.' ); } }) };
Requiring Single Child
你可以使用React.PropTypes.element指定仅可以将单一子元素作为子节点传递给组件。
class MyComponent extends React.Component { render() { // This must be exactly one element or it will warn. const children = this.props.children; return ( <div> {children} </div> ); } } MyComponent.propTypes = { children: PropTypes.element.isRequired };
默认Prop值
通过赋值特殊的defaultProps属性,你可以为props定义默认值:
class Greeting extends React.Component { render() { return ( <h1>Hello, {this.props.name}</h1> ); } } // Specifies the default values for props: Greeting.defaultProps = { name: 'Stranger' }; // Renders "Hello, Stranger": ReactDOM.render( <Greeting />, document.getElementById('example') );
如果父组件没有为this.props.name传值,defaultProps会给其一个默认值。propTypes的类型检测是在defaultProps解析之后发生的,因此也会对默认属性defaultProps进行类型检测。
4.无状态组件的检查和默认设置
如下面所示,对无状态组件进行设置
import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { View, Text, TextInput } from 'react-native'; const TextSegment = (props) => { const { behindStyle, delimiter, delimiterStyle, frontStyle, value, style, } = props; let frontValue = ''; let behindValue = ''; const splits = value && delimiter && value.split(delimiter); if (splits && splits.length) { frontValue = splits[0]; behindValue = splits[1]; } if (!delimiter) { return ( <View style={[{ flexDirection: 'row' }, style]}> <Text style={frontStyle}>{value}</Text> </View> ); } return ( <View style={[{ flexDirection: 'row' }, style]}> <Text style={frontStyle}>{frontValue}</Text> <Text style={delimiterStyle}>{delimiter}</Text> <Text style={behindStyle}>{behindValue}</Text> </View> ); }; TextSegment.propTypes = { frontStyle: TextInput.propTypes.style, delimiterStyle: TextInput.propTypes.style, behindStyle: TextInput.propTypes.style, style: View.propTypes.style, delimiter: PropTypes.string, value: PropTypes.string, }; TextSegment.defaultProps = { style: { alignItems: 'flex-end', }, value: '', }; export default TextSegment;
在上面代码中,通过方法名进行引用propTypes和defaultProps,其他用法和组件中使用一致。