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