Convert ReactDOMTextarea to not be a wrapper
Ben Alpert committed
Jun 4, 2015 at 13:08 UTC
d2e7e56cc4b05ffc7731bef5b7555fc23339fa55
4 files changed
+66
-67
src/renderers/dom/client/wrappers/ReactDOMInput.js
-10
@@ -11,7 +11,6 @@
11
12
'use strict';
13
14
-var AutoFocusUtils = require('AutoFocusUtils');
14
var ReactDOMIDOperations = require('ReactDOMIDOperations');
15
var LinkedValueUtils = require('LinkedValueUtils');
16
var ReactMount = require('ReactMount');
@@ -78,15 +77,6 @@ var ReactDOMInput = {
77
instancesByReactID[inst._rootNodeID] = inst;
78
},
79
81
- postMountWrapper: function(inst, transaction, props) {
82
- if (props.autoFocus) {
83
- transaction.getReactMountReady().enqueue(
84
- AutoFocusUtils.focusDOMComponent,
85
- inst
86
- );
87
- }
88
- },
89
-
80
unmountWrapper: function(inst) {
81
delete instancesByReactID[inst._rootNodeID];
82
},
src/renderers/dom/client/wrappers/ReactDOMTextarea.js
+45
-54
@@ -11,26 +11,18 @@
11
12
'use strict';
13
14
-var AutoFocusUtils = require('AutoFocusUtils');
15
-var DOMPropertyOperations = require('DOMPropertyOperations');
14
var LinkedValueUtils = require('LinkedValueUtils');
17
-var ReactBrowserComponentMixin = require('ReactBrowserComponentMixin');
18
-var ReactClass = require('ReactClass');
19
-var ReactElement = require('ReactElement');
20
-var ReactInstanceMap = require('ReactInstanceMap');
15
+var ReactDOMIDOperations = require('ReactDOMIDOperations');
16
var ReactUpdates = require('ReactUpdates');
17
18
var assign = require('Object.assign');
24
-var findDOMNode = require('findDOMNode');
19
var invariant = require('invariant');
26
-
20
var warning = require('warning');
21
29
-var textarea = ReactElement.createFactory('textarea');
30
-
22
function forceUpdateIfMounted() {
32
- if (this.isMounted()) {
33
- this.forceUpdate();
23
+ if (this._rootNodeID) {
24
+ // DOM component is still mounted; update
25
+ ReactDOMTextarea.updateWrapper(this);
26
}
27
}
28
@@ -49,24 +41,35 @@ function forceUpdateIfMounted() {
41
* The rendered element will be initialized with an empty value, the prop
42
* `defaultValue` if specified, or the children content (deprecated).
43
*/
52
-var ReactDOMTextarea = ReactClass.createClass({
53
- displayName: 'ReactDOMTextarea',
54
- tagName: 'TEXTAREA',
44
+var ReactDOMTextarea = {
45
+ getNativeProps: function(inst, props, context) {
46
+ invariant(
47
+ props.dangerouslySetInnerHTML == null,
48
+ '`dangerouslySetInnerHTML` does not make sense on <textarea>.'
49
+ );
50
56
- mixins: [AutoFocusUtils.Mixin, ReactBrowserComponentMixin],
51
+ // Always set children to the same thing. In IE9, the selection range will
52
+ // get reset if `textContent` is mutated.
53
+ var nativeProps = assign({}, props, {
54
+ defaultValue: undefined,
55
+ value: undefined,
56
+ children: inst._wrapperState.initialValue,
57
+ onChange: inst._wrapperState.onChange,
58
+ });
59
+
60
+ return nativeProps;
61
+ },
62
58
- componentWillMount: function() {
63
+ mountWrapper: function(inst, props) {
64
LinkedValueUtils.checkPropTypes(
65
'textarea',
61
- this.props,
62
- ReactInstanceMap.get(this)._currentElement._owner
66
+ props,
67
+ inst._currentElement._owner
68
);
64
- },
69
66
- getInitialState: function() {
67
- var defaultValue = this.props.defaultValue;
70
+ var defaultValue = props.defaultValue;
71
// TODO (yungsters): Remove support for children content in <textarea>.
69
- var children = this.props.children;
72
+ var children = props.children;
73
if (children != null) {
74
if (__DEV__) {
75
warning(
@@ -92,50 +95,38 @@ var ReactDOMTextarea = ReactClass.createClass({
95
if (defaultValue == null) {
96
defaultValue = '';
97
}
95
- var value = LinkedValueUtils.getValue(this.props);
96
- return {
98
+ var value = LinkedValueUtils.getValue(props);
99
+
100
+ inst._wrapperState = {
101
// We save the initial value so that `ReactDOMComponent` doesn't update
102
// `textContent` (unnecessary since we update value).
103
// The initial value can be a boolean or object so that's why it's
104
// forced to be a string.
105
initialValue: '' + (value != null ? value : defaultValue),
106
+ onChange: _handleChange.bind(inst),
107
};
108
},
109
105
- render: function() {
106
- // Clone `this.props` so we don't mutate the input.
107
- var props = assign({}, this.props);
108
-
109
- invariant(
110
- props.dangerouslySetInnerHTML == null,
111
- '`dangerouslySetInnerHTML` does not make sense on <textarea>.'
112
- );
113
-
114
- props.defaultValue = null;
115
- props.value = null;
116
- props.onChange = this._handleChange;
117
-
118
- // Always set children to the same thing. In IE9, the selection range will
119
- // get reset if `textContent` is mutated.
120
- return textarea(props, this.state.initialValue);
121
- },
122
-
123
- componentDidUpdate: function(prevProps, prevState, prevContext) {
124
- var value = LinkedValueUtils.getValue(this.props);
110
+ updateWrapper: function(inst) {
111
+ var props = inst._currentElement.props;
112
+ var value = LinkedValueUtils.getValue(props);
113
if (value != null) {
126
- var rootNode = findDOMNode(this);
114
// Cast `value` to a string to ensure the value is set correctly. While
115
// browsers typically do this as necessary, jsdom doesn't.
129
- DOMPropertyOperations.setValueForProperty(rootNode, 'value', '' + value);
116
+ ReactDOMIDOperations.updatePropertyByID(
117
+ inst._rootNodeID,
118
+ 'value',
119
+ '' + value
120
+ );
121
}
122
},
123
+};
124
133
- _handleChange: function(event) {
134
- var returnValue = LinkedValueUtils.executeOnChange(this.props, event);
135
- ReactUpdates.asap(forceUpdateIfMounted, this);
136
- return returnValue;
137
- },
138
-
139
-});
125
+function _handleChange(event) {
126
+ var props = this._currentElement.props;
127
+ var returnValue = LinkedValueUtils.executeOnChange(props, event);
128
+ ReactUpdates.asap(forceUpdateIfMounted, this);
129
+ return returnValue;
130
+}
131
132
module.exports = ReactDOMTextarea;
src/renderers/dom/shared/ReactDOMComponent.js
+21
-1
@@ -14,6 +14,7 @@
14
15
'use strict';
16
17
+var AutoFocusUtils = require('AutoFocusUtils');
18
var CSSPropertyOperations = require('CSSPropertyOperations');
19
var DOMProperty = require('DOMProperty');
20
var DOMPropertyOperations = require('DOMPropertyOperations');
@@ -21,6 +22,7 @@ var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
22
var ReactComponentBrowserEnvironment =
23
require('ReactComponentBrowserEnvironment');
24
var ReactDOMInput = require('ReactDOMInput');
25
+var ReactDOMTextarea = require('ReactDOMTextarea');
26
var ReactMount = require('ReactMount');
27
var ReactMultiChild = require('ReactMultiChild');
28
var ReactPerf = require('ReactPerf');
@@ -286,6 +288,10 @@ ReactDOMComponent.Mixin = {
288
ReactDOMInput.mountWrapper(this, props);
289
props = ReactDOMInput.getNativeProps(this, props, context);
290
break;
291
+ case 'textarea':
292
+ ReactDOMTextarea.mountWrapper(this, props);
293
+ props = ReactDOMTextarea.getNativeProps(this, props, context);
294
+ break;
295
}
296
297
assertValidProps(this, props);
@@ -304,7 +310,13 @@ ReactDOMComponent.Mixin = {
310
311
switch (this._tag) {
312
case 'input':
307
- ReactDOMInput.postMountWrapper(this, transaction, props);
313
+ case 'textarea':
314
+ if (props.autoFocus) {
315
+ transaction.getReactMountReady().enqueue(
316
+ AutoFocusUtils.focusDOMComponent,
317
+ this
318
+ );
319
+ }
320
break;
321
}
322
@@ -458,6 +470,11 @@ ReactDOMComponent.Mixin = {
470
lastProps = ReactDOMInput.getNativeProps(this, lastProps);
471
nextProps = ReactDOMInput.getNativeProps(this, nextProps);
472
break;
473
+ case 'textarea':
474
+ ReactDOMTextarea.updateWrapper(this);
475
+ lastProps = ReactDOMTextarea.getNativeProps(this, lastProps);
476
+ nextProps = ReactDOMTextarea.getNativeProps(this, nextProps);
477
+ break;
478
}
479
480
assertValidProps(this, nextProps);
@@ -656,6 +673,9 @@ ReactDOMComponent.Mixin = {
673
case 'input':
674
ReactDOMInput.unmountWrapper(this);
675
break;
676
+ case 'textarea':
677
+ ReactDOMTextarea.unmountWrapper(this);
678
+ break;
679
case 'html':
680
case 'head':
681
case 'body':
src/renderers/dom/shared/ReactDefaultInjection.js
-2
@@ -31,7 +31,6 @@ var ReactDOMIDOperations = require('ReactDOMIDOperations');
31
var ReactDOMIframe = require('ReactDOMIframe');
32
var ReactDOMOption = require('ReactDOMOption');
33
var ReactDOMSelect = require('ReactDOMSelect');
34
-var ReactDOMTextarea = require('ReactDOMTextarea');
34
var ReactDOMTextComponent = require('ReactDOMTextComponent');
35
var ReactElement = require('ReactElement');
36
var ReactEventListener = require('ReactEventListener');
@@ -117,7 +116,6 @@ function inject() {
116
'img': ReactDOMImg,
117
'option': ReactDOMOption,
118
'select': ReactDOMSelect,
120
- 'textarea': ReactDOMTextarea,
119
});
120
121
ReactInjection.DOMProperty.injectDOMPropertyConfig(HTMLDOMPropertyConfig);