1
- import { PureComponent , createElement } from 'react' ;
1
+ import { PureComponent , createElement , createRef } from 'react' ;
2
2
import { Scope } from './scope' ;
3
3
4
4
type Props = {
@@ -12,20 +12,76 @@ type State = {
12
12
flip : boolean ;
13
13
} ;
14
14
15
+ let moduleEntries : any = [ ]
16
+
17
+ let onMounts : any [ ] = [ ]
18
+ let onUpdates : any [ ] = [ ]
19
+ let onUnmounts : any [ ] = [ ]
20
+
21
+ export function setModules ( mods : any ) {
22
+ if ( mods === null || typeof mods !== 'object' ) return ;
23
+ moduleEntries = Object . entries ( mods )
24
+ onMounts = moduleEntries . map ( mod => [ mod [ 0 ] , mod [ 1 ] . componentDidMount ] ) . filter ( mod => mod [ 1 ] )
25
+ onUpdates = moduleEntries . map ( mod => [ mod [ 0 ] , mod [ 1 ] . componentDidUpdate ] ) . filter ( mod => mod [ 1 ] )
26
+ onUnmounts = moduleEntries . map ( mod => [ mod [ 0 ] , mod [ 1 ] . componentWillUnmount ] ) . filter ( mod => mod [ 1 ] )
27
+ }
28
+
29
+ export function hasModuleProps ( props ) {
30
+ return props
31
+ ? moduleEntries . some ( ( [ mkey ] ) => props . hasOwnProperty ( mkey ) )
32
+ : false
33
+ }
34
+
35
+ function moduleProcessor ( base , current , props ) {
36
+ if ( current && base . length ) {
37
+ base . forEach ( ( [ key , f ] ) => {
38
+ const prop = props [ key ]
39
+ if ( prop ) f ( current , prop )
40
+ } ) ;
41
+ }
42
+ }
43
+
15
44
export default class Incorporator extends PureComponent < Props , State > {
45
+ private ref : any ;
46
+ private selector : string | symbol ;
47
+ private unsubscribe : any ;
48
+ private element : any ;
49
+ private setRef : any ;
50
+
16
51
constructor ( props : Props ) {
17
52
super ( props ) ;
53
+ this . element = null
54
+
18
55
this . state = { flip : false } ;
19
56
this . selector = props . targetProps . sel ;
20
- }
21
57
22
- private selector : string | symbol ;
23
- private unsubscribe : any ;
58
+ const useRef = hasModuleProps ( props . targetProps )
59
+ if ( props . targetRef ) {
60
+ if ( typeof props . targetRef === 'function' && useRef ) {
61
+ this . setRef = element => {
62
+ this . element = element ;
63
+ props . targetRef ( element ) ;
64
+ } ;
65
+
66
+ this . ref = this . setRef ;
67
+ } else {
68
+ this . ref = props . targetRef ;
69
+ }
70
+ } else {
71
+ this . ref = useRef ? createRef ( ) : null ;
72
+ }
73
+ }
24
74
25
75
public componentDidMount ( ) {
26
76
this . unsubscribe = this . props . scope . subscribe ( this . selector , ( ) => {
27
77
this . setState ( ( prev : any ) => ( { flip : ! prev . flip } ) ) ;
28
78
} ) ;
79
+
80
+ moduleProcessor ( onMounts , this . element || ( this . ref && this . ref . current ) , this . props . targetProps )
81
+ }
82
+
83
+ public componentDidUpdate ( ) {
84
+ moduleProcessor ( onUpdates , this . element || ( this . ref && this . ref . current ) , this . props . targetProps )
29
85
}
30
86
31
87
private incorporateHandlers < P > ( props : P , scope : Scope ) : P {
@@ -38,27 +94,31 @@ export default class Incorporator extends PureComponent<Props, State> {
38
94
}
39
95
40
96
private materializeTargetProps ( ) {
41
- const { targetProps, targetRef , scope} = this . props ;
97
+ const { targetProps, scope} = this . props ;
42
98
let output = { ...targetProps } ;
43
99
output = this . incorporateHandlers ( output , scope ) ;
44
- if ( targetRef ) {
45
- output . ref = targetRef ;
100
+ if ( this . ref ) {
101
+ output . ref = this . ref ;
46
102
}
47
103
delete output . sel ;
104
+ moduleEntries . forEach ( pair => delete output [ pair [ 0 ] ] )
48
105
return output ;
49
106
}
50
107
51
108
public render ( ) {
52
109
const { target} = this . props ;
53
110
const targetProps = this . materializeTargetProps ( ) ;
111
+
54
112
if ( targetProps . children ) {
55
113
return createElement ( target , targetProps , targetProps . children ) ;
56
114
} else {
57
115
return createElement ( target , targetProps ) ;
58
116
}
59
117
}
60
118
61
- public componentWillUnmount ( ) {
119
+ public componentWillUnmount ( ) {
120
+ moduleProcessor ( onUnmounts , this . element || ( this . ref && this . ref . current ) , this . props . targetProps )
121
+
62
122
this . unsubscribe ( ) ;
63
123
}
64
124
}
0 commit comments