@samitouri / QOS-React-2 / commits / d2e7e56cc4

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);