@@ -15,19 +15,48 @@ function getDefaultName(name: string = '') {
15
15
return 'default' + name [ 0 ] . toUpperCase ( ) + name . slice ( 1 )
16
16
}
17
17
18
+ function normalizePropList ( propList : Prop [ ] ) : StrictProp [ ] {
19
+ return propList . map ( prop => {
20
+ if ( typeof prop === 'string' ) {
21
+ return {
22
+ withDefault : true ,
23
+ eq : defaultEq ,
24
+ name : prop
25
+ }
26
+ }
27
+ return {
28
+ withDefault : true ,
29
+ eq : defaultEq ,
30
+ ...prop
31
+ }
32
+ } )
33
+ }
34
+
35
+ /**
36
+ * @typedef StrictProp
37
+ * @public
38
+ * @param name {string}
39
+ * @param [withDefault=true] {boolean} - Whether check `default{propKey}` firstly
40
+ * @param [eq=(a, b) => a === b] {Function} - Detect new value and old value is equal
41
+ */
42
+ export type StrictProp = { name : string ; withDefault ?: boolean ; eq ?: ( oldValue , newValue ) => boolean }
43
+
44
+ /**
45
+ * @typedef Prop {string | StrictProp}
46
+ * @public
47
+ */
48
+ export type Prop = string | StrictProp
49
+
50
+ const defaultEq = ( a , b ) => a === b
51
+
18
52
/**
19
53
*
20
54
* @public
21
- * @param propList {string[]} eg. `['value']`
22
- * @param {{} } options
23
- * @param {boolean } [options.withDefault = true] - Whether check `default{propKey}` firstly
55
+ * @param propList {Prop[]} eg. `['value']` / `[{ name: 'value', withDefault: false }]`
24
56
* @return {Function } `(Component: React.ComponentClass) => React.ComponentClass`
25
57
*/
26
- export default function uncontrolled ( propList = [ ] , { withDefault = true } = { } ) {
27
- logger . invariant (
28
- Array . isArray ( propList ) && propList . every ( x => typeof x === 'string' ) ,
29
- `\`propList\` should be string[], but ${ typeof propList } `
30
- )
58
+ export default function uncontrolled ( propList : Prop [ ] = [ ] ) {
59
+ let propArray = normalizePropList ( propList )
31
60
32
61
return function uncontrolled ( Component : React . ComponentClass ) : React . ComponentClass {
33
62
logger . invariant ( isComponentClass ( Component ) , `\`Component\` should be a react component class` )
@@ -42,18 +71,19 @@ export default function uncontrolled(propList = [], { withDefault = true } = {})
42
71
constructor ( props ) {
43
72
super ( props )
44
73
this . state = this . state || { }
45
- propList . forEach ( prop => {
46
- if ( withDefault ) {
47
- const defaultPropName = getDefaultName ( prop )
48
- this . state [ prop ] =
49
- typeof this . props [ prop ] === 'undefined'
74
+ propArray . forEach ( prop => {
75
+ const propName = prop . name
76
+ if ( prop . withDefault ) {
77
+ const defaultPropName = getDefaultName ( propName )
78
+ this . state [ propName ] =
79
+ typeof this . props [ propName ] === 'undefined'
50
80
? typeof this . props [ defaultPropName ] === 'undefined'
51
- ? this . state [ prop ]
81
+ ? this . state [ propName ]
52
82
: this . props [ defaultPropName ]
53
- : this . props [ prop ]
83
+ : this . props [ propName ]
54
84
} else {
55
- if ( typeof this . props [ prop ] !== 'undefined' ) {
56
- this . state [ prop ] = this . props [ prop ]
85
+ if ( typeof this . props [ propName ] !== 'undefined' ) {
86
+ this . state [ propName ] = this . props [ propName ]
57
87
}
58
88
}
59
89
} )
@@ -66,9 +96,10 @@ export default function uncontrolled(propList = [], { withDefault = true } = {})
66
96
67
97
const newState = { }
68
98
let hasNewRecord = false
69
- propList . forEach ( prop => {
70
- if ( typeof newProps [ prop ] !== 'undefined' && this . state [ prop ] !== newProps [ prop ] ) {
71
- newState [ prop ] = newProps [ prop ]
99
+ propArray . forEach ( prop => {
100
+ const { name : propName , eq = defaultEq } = prop
101
+ if ( typeof newProps [ propName ] !== 'undefined' && ! eq ( this . state [ propName ] , newProps [ propName ] ) ) {
102
+ newState [ propName ] = newProps [ propName ]
72
103
hasNewRecord = true
73
104
}
74
105
} )
0 commit comments