1
+ 'use strict' ;
2
+
3
+ Object . defineProperty ( exports , "__esModule" , {
4
+ value : true
5
+ } ) ;
6
+
7
+ var _get = function get ( object , property , receiver ) { if ( object === null ) object = Function . prototype ; var desc = Object . getOwnPropertyDescriptor ( object , property ) ; if ( desc === undefined ) { var parent = Object . getPrototypeOf ( object ) ; if ( parent === null ) { return undefined ; } else { return get ( parent , property , receiver ) ; } } else if ( "value" in desc ) { return desc . value ; } else { var getter = desc . get ; if ( getter === undefined ) { return undefined ; } return getter . call ( receiver ) ; } } ;
8
+
9
+ var _createClass = function ( ) { function defineProperties ( target , props ) { for ( var i = 0 ; i < props . length ; i ++ ) { var descriptor = props [ i ] ; descriptor . enumerable = descriptor . enumerable || false ; descriptor . configurable = true ; if ( "value" in descriptor ) descriptor . writable = true ; Object . defineProperty ( target , descriptor . key , descriptor ) ; } } return function ( Constructor , protoProps , staticProps ) { if ( protoProps ) defineProperties ( Constructor . prototype , protoProps ) ; if ( staticProps ) defineProperties ( Constructor , staticProps ) ; return Constructor ; } ; } ( ) ;
10
+
11
+ exports . default = easyComp ;
12
+
13
+ var _react = require ( 'react' ) ;
14
+
15
+ var _observerUtil = require ( '@nx-js/observer-util' ) ;
16
+
17
+ var _autoBind = require ( './autoBind' ) ;
18
+
19
+ var _autoBind2 = _interopRequireDefault ( _autoBind ) ;
20
+
21
+ function _interopRequireDefault ( obj ) { return obj && obj . __esModule ? obj : { default : obj } ; }
22
+
23
+ function _classCallCheck ( instance , Constructor ) { if ( ! ( instance instanceof Constructor ) ) { throw new TypeError ( "Cannot call a class as a function" ) ; } }
24
+
25
+ function _possibleConstructorReturn ( self , call ) { if ( ! self ) { throw new ReferenceError ( "this hasn't been initialised - super() hasn't been called" ) ; } return call && ( typeof call === "object" || typeof call === "function" ) ? call : self ; }
26
+
27
+ function _inherits ( subClass , superClass ) { if ( typeof superClass !== "function" && superClass !== null ) { throw new TypeError ( "Super expression must either be null or a function, not " + typeof superClass ) ; } subClass . prototype = Object . create ( superClass && superClass . prototype , { constructor : { value : subClass , enumerable : false , writable : true , configurable : true } } ) ; if ( superClass ) Object . setPrototypeOf ? Object . setPrototypeOf ( subClass , superClass ) : subClass . __proto__ = superClass ; }
28
+
29
+ var REACTIVE_RENDER = Symbol ( 'reactive render' ) ;
30
+
31
+ function easyComp ( Comp ) {
32
+ if ( typeof Comp !== 'function' ) {
33
+ throw new TypeError ( 'easyComp expects a component as argument.' ) ;
34
+ }
35
+
36
+ // wrap stateless components in a class
37
+ if ( isStatelessComp ( Comp ) ) {
38
+ Comp = statelessToStatefulComp ( Comp ) ;
39
+ } else if ( hasComponentShouldUpdate ( Comp ) ) {
40
+ // shouldComponentUpdate is optimized by easyState, overwriting it would add zero or less value
41
+ throw new Error ( 'easyState optimizes shouldComponentUpdate, do not implement it.' ) ;
42
+ }
43
+
44
+ return toReactiveComp ( Comp ) ;
45
+ }
46
+
47
+ function isStatelessComp ( Comp ) {
48
+ return ! ( Comp . prototype && Comp . prototype . render ) && ! _react . Component . isPrototypeOf ( Comp ) ;
49
+ }
50
+
51
+ function statelessToStatefulComp ( StatelessComp ) {
52
+ var _class , _temp ;
53
+
54
+ return _temp = _class = function ( _Component ) {
55
+ _inherits ( StatefulComp , _Component ) ;
56
+
57
+ function StatefulComp ( ) {
58
+ _classCallCheck ( this , StatefulComp ) ;
59
+
60
+ return _possibleConstructorReturn ( this , ( StatefulComp . __proto__ || Object . getPrototypeOf ( StatefulComp ) ) . apply ( this , arguments ) ) ;
61
+ }
62
+
63
+ _createClass ( StatefulComp , [ {
64
+ key : 'render' ,
65
+
66
+
67
+ // call the original function component inside the render method
68
+
69
+ // proxy react specific static variables to the stateful component
70
+ // from the stateless component
71
+ value : function render ( ) {
72
+ return StatelessComp . call ( this , this . props , this . context ) ;
73
+ }
74
+ } ] ) ;
75
+
76
+ return StatefulComp ;
77
+ } ( _react . Component ) , _class . displayName = StatelessComp . displayName || StatelessComp . name , _class . contextTypes = StatelessComp . contextTypes , _class . propTypes = StatelessComp . propTypes , _class . defaultProps = StatelessComp . defaultProps , _temp ;
78
+ }
79
+
80
+ function hasComponentShouldUpdate ( Comp ) {
81
+ return typeof Comp . prototype . shouldComponentUpdate === 'function' ;
82
+ }
83
+
84
+ function toReactiveComp ( Comp ) {
85
+ var _class2 , _temp2 ;
86
+
87
+ // return a HOC which overwrites render, shouldComponentUpdate and componentWillUnmount
88
+ // it decides when to run the new reactive methods and when to proxy to the original methods
89
+ return _temp2 = _class2 = function ( _Comp ) {
90
+ _inherits ( EasyHOC , _Comp ) ;
91
+
92
+ // proxy react specific static variables to the HOC from the component
93
+ function EasyHOC ( props ) {
94
+ _classCallCheck ( this , EasyHOC ) ;
95
+
96
+ // auto bind non react specific original methods to the component instance
97
+ var _this2 = _possibleConstructorReturn ( this , ( EasyHOC . __proto__ || Object . getPrototypeOf ( EasyHOC ) ) . call ( this , props ) ) ;
98
+
99
+ ( 0 , _autoBind2 . default ) ( _this2 , Comp . prototype , true ) ;
100
+
101
+ // turn the state into an observable object, which triggers rendering on mutations
102
+ _this2 . state = ( 0 , _observerUtil . observable ) ( _this2 . state ) ;
103
+ return _this2 ;
104
+ }
105
+
106
+ _createClass ( EasyHOC , [ {
107
+ key : 'render' ,
108
+ value : function render ( ) {
109
+ var _this3 = this ;
110
+
111
+ // if it is the first direct render from react call there is no reactive render yet
112
+ if ( ! this [ REACTIVE_RENDER ] ) {
113
+ var result = void 0 ;
114
+ // create a reactive render, which is automatically called by easyState on relevant state and store mutations
115
+ // the passed function is executed right away synchronously once by easyState
116
+ this [ REACTIVE_RENDER ] = ( 0 , _observerUtil . observe ) ( function ( ) {
117
+ // if it is the first (synchronous) execution, call the original component's render
118
+ // this is necessary because forceUpdate can not be called synchronously inside render functions
119
+ if ( ! _this3 [ REACTIVE_RENDER ] ) {
120
+ result = _get ( EasyHOC . prototype . __proto__ || Object . getPrototypeOf ( EasyHOC . prototype ) , 'render' , _this3 ) . call ( _this3 ) ;
121
+ } else {
122
+ // if it is a later reactive, asynchronous execution - triggered by easyState - forceUpdate the original component
123
+ // this is necessary, because calling render would require the result to be returned
124
+ // which is not possible from this asynchronous context
125
+ _get ( EasyHOC . prototype . __proto__ || Object . getPrototypeOf ( EasyHOC . prototype ) , 'forceUpdate' , _this3 ) . call ( _this3 ) ;
126
+ }
127
+ } ) ;
128
+ // return the result from super.render() inside the reactive render on the first render execution
129
+ return result ;
130
+ } else {
131
+ // return the original component's render result on direct calls from react
132
+ return _get ( EasyHOC . prototype . __proto__ || Object . getPrototypeOf ( EasyHOC . prototype ) , 'render' , this ) . call ( this ) ;
133
+ }
134
+ }
135
+
136
+ // react should trigger updates on prop changes, while easyState handles state changes
137
+
138
+ } , {
139
+ key : 'shouldComponentUpdate' ,
140
+ value : function shouldComponentUpdate ( nextProps ) {
141
+ var props = this . props ;
142
+
143
+ var keys = Object . keys ( props ) ;
144
+ var nextKeys = Object . keys ( nextProps ) ;
145
+
146
+ // component should update if the number of its props changed
147
+ if ( keys . length !== nextKeys . length ) {
148
+ return true ;
149
+ }
150
+
151
+ // component should update if any of its props changed value
152
+ var _iteratorNormalCompletion = true ;
153
+ var _didIteratorError = false ;
154
+ var _iteratorError = undefined ;
155
+
156
+ try {
157
+ for ( var _iterator = keys [ Symbol . iterator ] ( ) , _step ; ! ( _iteratorNormalCompletion = ( _step = _iterator . next ( ) ) . done ) ; _iteratorNormalCompletion = true ) {
158
+ var key = _step . value ;
159
+
160
+ if ( props [ key ] !== nextProps [ key ] ) {
161
+ return true ;
162
+ }
163
+ }
164
+
165
+ // do not let react update the comp otherwise, leave state triggered updates to easyState
166
+ } catch ( err ) {
167
+ _didIteratorError = true ;
168
+ _iteratorError = err ;
169
+ } finally {
170
+ try {
171
+ if ( ! _iteratorNormalCompletion && _iterator . return ) {
172
+ _iterator . return ( ) ;
173
+ }
174
+ } finally {
175
+ if ( _didIteratorError ) {
176
+ throw _iteratorError ;
177
+ }
178
+ }
179
+ }
180
+
181
+ return false ;
182
+ }
183
+ } , {
184
+ key : 'componentWillUnmount' ,
185
+ value : function componentWillUnmount ( ) {
186
+ // clean up memory used by easyState
187
+ ( 0 , _observerUtil . unobserve ) ( this [ REACTIVE_RENDER ] ) ;
188
+
189
+ // also call user defined componentWillUnmount to allow the user
190
+ // to clean up additional memory
191
+ if ( _get ( EasyHOC . prototype . __proto__ || Object . getPrototypeOf ( EasyHOC . prototype ) , 'componentWillUnmount' , this ) ) {
192
+ _get ( EasyHOC . prototype . __proto__ || Object . getPrototypeOf ( EasyHOC . prototype ) , 'componentWillUnmount' , this ) . call ( this ) ;
193
+ }
194
+ }
195
+ } ] ) ;
196
+
197
+ return EasyHOC ;
198
+ } ( Comp ) , _class2 . displayName = Comp . displayName || Comp . name , _class2 . contextTypes = Comp . contextTypes , _class2 . propTypes = Comp . propTypes , _class2 . defaultProps = Comp . defaultProps , _temp2 ;
199
+ }
0 commit comments