此文件纪录 React PropTypes 的使用方式与语法
相信读者在使用纯 JavaScript 的时候一定有遇过搞不清楚 function 参数的型别的状况。在使用 React component 时也是,如果没有好好定义 component props 型别的话,每次使用 component 都会要去查程序码才能知道每个 props 如何使用,这将会造成开发上的困难。
所幸 React 内建就有提供方法检查 component 每个 props 的型别。此内建的检查方法就是本篇文章要介绍的主题:PropTypes 与 DefaultProps。
除了使用 Flow、TypeScript 等 JavaScript 静态语法检查器来检查以外,React 在每个 component 中也提供了 propTypes
属性来检查 props 的型别。
一个简单的范例如下:
function Profile(props) {
return <div>{props.name}, {props.age}</div>
}
Profile.propTypes = {
name: PropTypes.string,
age: PropTypes.number,
}
更详细一点讲,PropTypes 的功能是以下两个:
定义 component prop 的型别
定义 component prop 的好处显而易见,他可以帮助我们更容易了解 component 的使用方式,不再需要进到 component 内的程序码即能知道 component 该如何使用。从某种角度来讲,他可以算是 component 的使用文件。
在 React development 模式下,runtime 去检查 component 的 prop 型别是否正确
如果在 development 模式下使用错误的 prop 型别,则 console 会发出警告。
以上面的 Profile
为范例范例,如果将 number 赋值给 Profile
的 name
prop,则 console 中会出现以下的警告:
<Profile name={123} />
// Warning: Failed prop type: Invalid prop `name` of type `number` supplied to `Profile`, expected `string`. in Profile
检查 component prop 可以帮助我们更快速发现错误,不会因为错误而逐一检查错误出在哪里,这可以有效地加快开发速度;PropTypes 也可以帮助我们提早发现错误,可减少 bug 被埋藏起来的问题。
然而检查型别毕竟是消耗效能的行为,所以 React 只会在 development 模式下检查 PropTypes 而已,在 production 模式下则不会检查。
接下来来看看如何使用 PropTypes。
React 在 15.5
版之後就将 PropTypes 从 React Core 函式库中搬移到 prop-types 这个 node module 上了,因此如果要使用 PropTypes,需要先进行安装:
npm install --save prop-types
?小提醒:
需要注意的是,虽然 React 底层是有用到 PropTypes node module 的,因此专案就算不安装,开发者还是可以的透过 React 的 dependency 间接的使用 PropTypes。
但因为 React 随时都有可能更新内部 dependency 的版号,甚至移除 node module,因此官方仍然建议应该要自己装(Create-React-App 创建的专案来说也应安装)。
PropTypes 的语法很简单。任何 component(不论是 class component、function component 还是 React.memo 跟 React.forwardRef 创建出来的 component)都可以加上 propTypes
这个属性来定义 component 的 props 型别:
import PropTypes from 'prop-types';
function MyComponent(props) { /* ... */ }
MyComponent.propTypes = {
propName1: propTypes.string,
propName2: propTypes.number,
// ...
}
Component.propTypes
属性的型别是 JavaScript object,此 object:
PropTypes
)提供的函式来定义型别,如 PropTypes.string
、PropTypes.number
...etc。prop-types 这个 node module 会 export 一个 PropTypes
物件。
PropTypes
物件中提供了各式各样的属性可以用来检查 props 的型别,例如:
PropTypes.array
PropTypes.bool
PropTypes.func
PropTypes.number
PropTypes.object
PropTypes.string
PropTypes.node
PropTypes.oneOf([])
// ...etc
这些 PropTypes 的每个属性其实本质上都是一个 validator function,可作为型别检查器用来检查 component props 的型别。
而每个 PropTypes 属性还可以再使用 isRequired
的属性,用来定义使用 component 时是否必须提供某个 prop:
PropTypes.array.isRequired
PropTypes.bool.isRequired
PropTypes.func.isRequired
PropTypes.number.isRequired
PropTypes.object.isRequired
PropTypes.string.isRequired
PropTypes.node.isRequired
PropTypes.oneOf([]).isRequired
// ...etc
同样的,PropTypes.xxx.isRequired
的本质也是 validator function,只是多做了 prop 是否存在的检查而已。
同样的道理,因为这些检查器实际上都只是 function 而已,所以开发者是能够客制化自己的 validator function 来做 props 的型别检查的。
接着我们将学习每个 PropTypes 属性的功能与用法。
使用以下的 PropTypes 属性可以检查 props 是否符合对应的 JavaScript 基本型别:
MyComponent.propTypes = {
optionalNumber: PropTypes.number,
optionalString: PropTypes.string,
optionalBool: PropTypes.bool,
optionalObject: PropTypes.object,
optionalSymbol: PropTypes.symbol,
optionalArray: PropTypes.array,
optionalFunc: PropTypes.func,
}
合法的 component props 范例如下:
<MyComponent
optionalNumber={123}
optionalString="123"
optionalBool={false}
optionalObject={{ test: 123 }}
optionalSymbol={Symbol()}
optionalArray={[1, 2, 3]}
optionalFunc={() => {}}
/>
PropTypes.node
可以用来检查 prop 是否是可以被 React render 的型别:
MyComponent.propTypes = {
optionalNode: PropTypes.node,
}
可以被 React render 的型别包括:
合法的 component props 范例如下:
<MyComponent
optionalNode={<div>123</div>}
// can also be:
// optionalNode={<Fragment></Fragment>}
// optionalNode={123}
// optionalNode="123"
// optionalNode={[1, 2, 3]}
/>
PropTypes.element
可以用来检查 prop 是否为 React element:
MyComponent.propTypes = {
optionalElement: PropTypes.element,
}
合法的 component props 范例如下:
<MyComponent
optionalElement={<div>123</div>}
// can also be:
// optionalElement={<Fragment></Fragment>}
/>
PropTypes.elementType
可以用来检查 prop 是否为合法 React element type:
MyComponent.propTypes = {
optionalElementType: PropTypes.element,
}
React element type 包括:
"div"
、"span"
...etc,会是用 string 表示)合法的 component props 范例如下:
class MyOtherComponent extends React.Component {
render() {/* ... */}
}
<MyComponent
optionalElementType={MyOtherComponent}
// can also be:
// optionalElementType="div"
// optionalElementType="span"
/>
PropTypes.instanceOf()
可以用来检查 prop 是否为某个 class 的 instance。
因此 instanceOf()
需要带入:
expectedClass
: 一个 class 型别范例如下:
class MyClass {/* ... */}
MyComponent.propTypes = {
optionalInstanceOf: PropTypes.instanceOf(MyClass),
}
合法的 component props 范例如下:
const myClass = new MyClass();
<MyComponent
optionalInstanceOf={myClass}
/>
PropTypes.oneOf()
可以用来检查 prop 是否为指定的值之一。
因此 oneOf()
需要带入:
expectedValues
:包含一组指定值的 array范例如下:
MyComponent.propTypes = {
optionalEnum: PropTypes.oneOf([123, 'Henry']),
}
需要注意的是,检查是否为指定值的方法是透过 Object.is(类似 ===
) 检查,因此不适合用来检查 prop 是否为特定内容的 object。如果有这个需求的话,应使用 PropTypes.shape
或 PropTypes.exact
。
合法的 component props 范例如下:
<MyComponent
optionalEnum={123}
// can also be:
// optionalEnum="Henry"
/>
PropTypes.oneOfType()
可以用来检查 prop 是否为指定的型别之一。
因此 oneOf()
需要带入:
expectedTypes
:包含一组指定型别的 array范例如下:
class MyClass {/* ... */}
MyComponent.propTypes = {
optionalUnion: PropTypes.oneOfType([
PropTypes.number,
PropTypes.string,
PropTypes.instanceOf(Message)
]),
}
合法的 component props 范例如下:
const myClass = new MyClass();
<MyComponent
optionalUnion={123}
// can also be:
// optionalUnion="Henry"
// optionalUnion={myClass}
/>
PropTypes.arrayOf()
可以用来检查 prop 是否为指定型别组成的 array。
因此 arrayOf()
需要带入:
expectedTypeChecker
:指定的 validator function(型别检查器)范例如下:
MyComponent.propTypes = {
optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
optionalMixedArrayOf: PropTypes.arrayOf(
PropTypes.oneOfType([PropTypes.number, PropTypes.string])
),
}
因为是带入的参数是 validator function,因此除了常见的基本型别检查器( PropTypes.number
、 PropTypes.string
...etc)以外,也可以发挥创意带入 PropTypes.oneOf
、 PropTypes.oneOfType()
等较复杂的检查器。
合法的 component props 范例如下:
<MyComponent
optionalArrayOf={[1, 3, 123, -1]}
optionalMixedArrayOf={[1, 'Henry', 123]}
/>
PropTypes.objectOf()
可以用来检查 prop 是否为指定型别组成的 object。
因此 objectOf()
需要带入:
expectedTypeChecker
:指定的 validator function(型别检查器)范例如下:
MyComponent.propTypes = {
optionalObjectOf: PropTypes.objectOf(PropTypes.number),
optionalMixedObjectOf: PropTypes.objectOf(
PropTypes.oneOfType([PropTypes.number, PropTypes.string])
),
}
与 PropTypes.arrayOf
相同,因为是带入的参数是 validator function,因此除了常见的基本型别检查器以外,也可以发挥创意带入 PropTypes.oneOf
、 PropTypes.oneOfType()
等较复杂的检查器。
合法的 component props 范例如下:
<MyComponent
optionalObjectOf={{ a: 1, b: 123, c: 345 }}
optionalMixedObjectOf={{ a: 1, b: 'Henry', c: 123 }}
/>
PropTypes.shape()
可以用来检查 prop 是否为指定 key 组成的 object。
因此 shape()
需要带入:
shapeTypes
:一个 object,包含指定的 key 与对应的 validator function(型别检查器)作为 valueMyComponent.propTypes = {
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number,
type: PropTypes.oneOf(['primary', 'secondary', 'warning'])
}),
}
同样的,因为 shapeTypes
中每个 key 的 value 都会是 validator function,因此除了基本型别检查器以外也可以带入 PropTypes.oneOf
、 PropTypes.oneOfType()
等较复杂的检查器。
合法的 component props 范例如下:
<MyComponent
optionalObjectWithShape={{ color: '#fff', fontSize: 400, type: 'primary' }}
/>
PropTypes.exact()
可以用来检查 prop 是否为指定 key 组成的 object,且此 object 不可以有额外的 key。如果有额外的 key,React 就会显示警告。
因此 exact()
需要带入:
exactShapeTypes
:一个 object,包含指定的 key 与对应的 validator function(型别检查器)作为 valueMyComponent.propTypes = {
optionalObjectWithStrictShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number,
type: PropTypes.oneOf(['primary', 'secondary', 'warning'])
}),
}
合法的 component props 范例如下:
<MyComponent
optionalObjectWithStrictShape={{ color: '#fff', fontSize: 400, type: 'primary' }}
/>
上述的 PropTypes 属性後面都可搭配 isRequired
使用,代表使用 component 时必须提供此 prop。
如果没有 isRequired
的话,则 prop 会是可提供,也可不提供的(Optional):
MyComponent.propTypes = {
optionalNumber: PropTypes.number,
requiredObjectWithStrictShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number,
type: PropTypes.oneOf(['primary', 'secondary', 'warning']).isRequired
}).isRequied,
}
合法的 component props 范例如下:
<MyComponent
// optionalNumber is an optional prop, so it's ok to not provide optionalNumber.
// ---
// requiredObjectWithStrictShape prop must be provide.
// but only 'type' key is required, other key are optional, so it's ok to not provide them.
requiredObjectWithStrictShape={{ type: 'primary' }}
/>
可以看到, optionalNumber
是可有可无的,因此不提供也是合法的。
requiredObjectWithStrictShape
则是必要的,但是此 object 的内容只有 type
是必须要提供的,其他不提供也算合法。
PropTypes.any
代表一个 prop 可以是任意的内容。
通常与 isRequired
一起使用,代表此 prop 必须存在,但可以是任意型别:
MyComponent.propTypes = {
any: PropTypes.any
requiredAny: PropTypes.any.isRequired
}
合法的 component props 范例如下:
<MyComponent
any: [1, 'test', <div />, true]
requiredAny: { a: 'test' }
/>
如 PropTypes 物件段落所讲,上述的 PropTypes 属性皆为 function,因此只要有了解这些 validator function 的 input 与 output,开发者也可客制化自己的型别检查器:
客制化的 validator function 可以带入以下三个参数:
props
:代表目前带入的所有 propspropName
:代表目前正在检查的 prop 名字componentName
:代表 component 的名字并在 prop 不符合格式时需要回传:
error
:Error
的 instance,代表格式错误,并可添加错误讯息此外,arrayOf()
、objectOf()
等较复杂的检查器内也可带入客制化的检查器,如下所示:
MyComponent.propTypes = {
// You can also specify a custom validator. It should return an Error
// object if the validation fails. Don't `console.warn` or throw, as this
// won't work inside `oneOfType`.
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error(
'Invalid prop `' + propName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
},
// You can also supply a custom validator to `arrayOf` and `objectOf`.
// It should return an Error object if the validation fails. The validator
// will be called for each key in the array or object. The first two
// arguments of the validator are the array or object itself, and the
// current item's 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.'
);
}
})
}
合法的 component props 范例如下:
<MyComponent
customProp: 'matchme'
customArrayProp: ['matchme', 'matchme123']
/>
Component 的 children 内容(props.children
)也是可以被检查的,如下所示:
MyComponent.propTypes = {
children: PropTypes.number
}
合法的 component props 范例如下:
<MyComponent>{123}</MyComponent>
如 所提,key
是 React 内部所使用的 prop,并不会传给 component 使用,所以应该不应该客制化 key
的内容。就算为 key
定义 propType,component 拿到的 key
内容也永远会是 undefined
。
如果在 PropTypes 中定义 key
时,React 就会报错:
MyComponent.propTypes = {
key: PropTypes.number
}
// Warning: Profile: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop
除了检查 props 的型别以外,React 在每个 component 中也提供了 defaultProps
属性来为 props 添加预设值。
如果上层 component 没有传对应的 props 下来,则 React 就会为 component 带入 defaultProps
设定的值。
让 component 有预设的行为时常可以避免一些基本且冗长的 prop 设定。一个简单的范例如下:
function Greetings(props) {
return <div>Hello, {props.name}</div>
}
Greetings.propTypes = {
name: PropTypes.string,
}
Greetings.defaultProps = {
name: 'Guest'
}
DefaultProps 的语法很简单。任何 component 都可以加上 defaultProps
这个属性来设定 component prop 的预设值:
function MyComponent(props) { /* ... */ }
MyComponent.defaultProps = {
propName1: 'someValue1',
propName2: 'someValue2',
// ...
}
Component.propTypes
属性的型别是 JavaScript object,此 object:
如果有使用 Babel 的 transform-class-properties 则也可以在 class component 中使用 static 语法定义 defaultProps
:
class Greeting extends React.Component {
static defaultProps = {
name: 'stranger'
}
render() {
return (
<div>Hello, {this.props.name}</div>
)
}
}
一个需要注意的点是,React 使用 component.propTypes
与 component.defaultProps
的顺序如下:
defaultProps
设定的预设值。propTypes
检查 props 的型别。因此就算 defaultProps 型别设定错误,React 的 propTypes 依然可以贴心的为开发者检查到问题,如下所示:
function Greetings(props) {
return <div>Hello, {props.name}</div>
}
Greetings.propTypes = {
name: PropTypes.string,
}
Greetings.defaultProps = {
name: 123
}
// Warning: Failed prop type: Invalid prop `name` of type `number` supplied to `Greetings`, expected `string`. in Greetings
在这个章节中,我们介绍的 React 的 PropTypes 与 DefaultProps。
PropTypes 是用来在 development 模式下检查 component prop 的型别。通常会与 prop-types 这个 node module 一起使用,此 node module 提供了一组 validator function 用来检查型别,
而开发者也可以实作自己的检查器 function 来检查 props 内容。
DefaultValue 则可以为 component 设定预设值,当 component 没有带入 prop 时,React 就会为 component 带入 defaultProps
设定的值。
最後在执行的顺序上 defaultProps 会先被设定後,React 才会进行 propTypes 的检查,因此 defaultProps 错误的时候 React 也会报错提醒。
>>: Nice day 29 (iphone10s 功能挖掘)-好用捷径介绍
请问各位大大,小的想去考111年的半导体布局设计工程师能力监定,请问哪里可以有实体或线上课程呢,上完...
GitHub 网址:https://github.com/ Heroku 网址:https://w...
1.首先粗浅的讲一下 HTML 的语法,如下: <!-- 以下这个半形的中括号,叫做标签 ; ...
前言 上一篇我们讨论DDD的战术设计,它建议引用各种设计模式,提高生产力,因此接下来,就来介绍各种设...
表单类型是网页很常见的呈现方式,表单元素有文字框<input>、<textarea...