【注意】虽然报错但是这并不会影响程序的正常运行(譬如上面我们看到渲染仍然是正常的),因为本质上说类型检测报的是非致命性错误warning而不是致命性错误error(区别在于是否影响了正常运行)。对objectOf也是同样的做法
3.5 通过shape方法检测目标对象不同属性的不同数据类型
如果你认真思考一下的话,你会发现3.4中的objectOf有一个缺陷,就是它内部的属性的数据类型被强行规定为一种,但通常一个对象里应该是有多种不同类型的属性了,那么这时候objectOf就不符合要求了,我们应该使用shape方法,其用法:
PropTypes.shape({ 属性1:类型1, 属性2:类型2, //... }),
举个例子:
import React from 'react' import PropTypes from 'prop-types'; class Son extends React.Component{ render(){ return (<div style ={{padding:30}}> {'我的名字叫' + this.props.object.name} <br/> {'我的年龄是' + this.props.object.age} </div>) } } Son.propTypes = { object:PropTypes.shape({ name:PropTypes.string, age:PropTypes.number }) } class Father extends React.Component{ render(){ return (<div> <Son object = {{name:'彭湖湾',age:20}}/> </div>) } }
无报错,把<Son object = {{name:'彭湖湾',age:20}}/>改成<Son object = {{name:'彭湖湾',age:'20'}}/>,然后就能喜闻乐见得报错了
3.6 通过isRequired检测props中某个必要的属性(如果该属性不存在就报错)
有时候,我们在对某个变量进行类型检测时,我们不仅要求它符合预期的类型,同时也要求它是必须写入的,这时候就要用到isRequired。
【分析】
Son.propTypes = { number:PropTypes.number }
这段代码的作用是当你在props中写入number属性且number属性类型错误时给予报错提示,可如果你压根就没有写入number属性呢?没错,什么错误都不会报。这就是使用isRequired的必要性
【栗子】
import React from 'react' import PropTypes from 'prop-types'; class Son extends React.Component{ render(){ return (<div style ={{padding:30}}> {this.props.number} </div>) } } Son.propTypes = { number:PropTypes.number } class Father extends React.Component{ render(){ return (<div> <Son /> </div>) } }
控制台无任何输出
如果我们改成:
Son.propTypes = { number:PropTypes.number.isRequired }
再运行,我们就又可以喜闻乐见得看到错误了:
【注意】在这里给大家提个问题:我们上述的写法是number:PropTypes.number.isRequired,这要求number是数字类型,但如果你不想控制number的类型而仅仅是想控制它的必要性呢?难道写成number:isRequired或number:PropTypes.isRequired? 这个时候PropTypes.any就登场啦!它代表了该变量可取任何一种数据类型,所以你可以写成这样——number: PropTypes.any.isRequired
3.7 应对更复杂的类型检测——将PropTypes的属性值写成函数
Son.propTypes = { prop:function(props,propName,componentName){ if(/*判断条件*/){ return new Error(/*错误的参数*/) } } }
在属性prop的类型检测中,属性值是一个函数,在这里props是包含prop的props对象,propName是prop的属性名,componentName是props所在的组件名称,函数的返回值是一个Error对象
import React from 'react' import PropTypes from 'prop-types'; class Son extends React.Component{ render(){ return (<div style ={{padding:30}}> {this.props.email} </div>) } } Son.propTypes = { email:function(props,propName,componentName){ if(!/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/.test(props[propName])){ return new Error('组件' + componentName+ '里的属性' + propName + '不符合邮箱的格式'); } } } class Father extends React.Component{ render(){ return (<div> <Son email = {2314838004}/> </div>) } }
在这里我们利用正则表达式检测传递到Son组件的email属性是否符合邮箱格式,如果不符合就抛出错误,那么2314838004显然不符合这一要求,所以我们就得到下面的demo:(其实加上qq.com就是我的邮箱啦 哈哈)
4.ES7下类型检测的新写法:
可能你觉得把propTypes写在类外看起来有些怪怪的,在ES7的静态类属性的支持下,你可以这样写:
class Son extends React.Component{ static propTypes = { //..类型检测 } render(){ return (/* 渲染*/) } }
但注意,这在ES7下生效
5.props-types的独立与react.PropTypes的弃用