@@ -6,6 +6,31 @@ import merge from 'deepmerge';
6
6
import ThemeProvider , { ThemeContext } from './ThemeProvider' ;
7
7
import type { Theme } from '../types' ;
8
8
9
+ const REACT_METHODS = [
10
+ 'autobind' ,
11
+ 'childContextTypes' ,
12
+ 'componentDidMount' ,
13
+ 'componentDidUpdate' ,
14
+ 'componentWillMount' ,
15
+ 'componentWillReceiveProps' ,
16
+ 'componentWillUnmount' ,
17
+ 'componentWillUpdate' ,
18
+ 'contextTypes' ,
19
+ 'displayName' ,
20
+ 'getChildContext' ,
21
+ 'getDefaultProps' ,
22
+ 'getDOMNode' ,
23
+ 'getInitialState' ,
24
+ 'mixins' ,
25
+ 'propTypes' ,
26
+ 'render' ,
27
+ 'replaceProps' ,
28
+ 'setProps' ,
29
+ 'shouldComponentUpdate' ,
30
+ 'statics' ,
31
+ 'updateComponent' ,
32
+ ] ;
33
+
9
34
const isClassComponent = ( Component : Function ) => ! ! Component . prototype . render ;
10
35
11
36
export default function withTheme < Props : { } > (
@@ -81,17 +106,46 @@ export default function withTheme<Props: {}>(
81
106
: this . _root ;
82
107
} ;
83
108
84
- // setNativeProps is used by Animated to set props on the native component
85
- /* $FlowFixMe */
86
- if ( Comp . prototype . setNativeProps ) {
87
- // $FlowFixMe
88
- ThemedComponent . prototype . setNativeProps = function setNativeProps (
89
- ...args
90
- ) {
91
- const root = this . getWrappedInstance ( ) ;
92
- return root . setNativeProps ( ...args ) ;
93
- } ;
94
- }
109
+ // Copy non-private methods and properties from underlying component
110
+ // This will take expose public methods and properties such as `focus`, `setNativeProps` etc.
111
+ // $FlowFixMe
112
+ Object . getOwnPropertyNames ( Comp . prototype )
113
+ . filter (
114
+ prop =>
115
+ ! (
116
+ REACT_METHODS . includes ( prop ) || // React specific methods and properties
117
+ prop in React . Component . prototype || // Properties from React's prototype such as `setState`
118
+ prop in ThemedComponent . prototype || // Properties from enhanced component's prototype
119
+ // Private methods
120
+ prop . startsWith ( '_' )
121
+ )
122
+ )
123
+ . forEach ( prop => {
124
+ // $FlowFixMe
125
+ if ( typeof Comp . prototype [ prop ] === 'function' ) {
126
+ /* eslint-disable func-names */
127
+ // $FlowFixMe
128
+ ThemedComponent . prototype [ prop ] = function ( ...args ) {
129
+ // Make sure the function is called with correct context
130
+ // $FlowFixMe
131
+ Comp . prototype [ prop ] . apply ( this . getWrappedInstance ( ) , args ) ;
132
+ } ;
133
+ // Set the function name for better debugging
134
+ // $FlowFixMe
135
+ ThemedComponent . prototype [ prop ] . name = prop ;
136
+ } else {
137
+ // Copy properties as getters and setters
138
+ // This make sure dynamic properties always stay up-to-date
139
+ Object . defineProperty ( ThemedComponent . prototype , prop , {
140
+ get ( ) {
141
+ return this . getWrappedInstance ( ) [ prop ] ;
142
+ } ,
143
+ set ( value ) {
144
+ this . getWrappedInstance ( ) [ prop ] = value ;
145
+ } ,
146
+ } ) ;
147
+ }
148
+ } ) ;
95
149
}
96
150
97
151
hoistNonReactStatics ( ThemedComponent , Comp ) ;
0 commit comments