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

DOM components as refs

Still missing: .props/.getDOMNode warnings.

Ben Alpert committed Jun 15, 2015 at 19:16 UTC ffd527f593c02b7e11ad4e912cfd1da549b0709e
12 files changed +35 -155
src/isomorphic/classic/element/ReactElementValidator.js
+2 -11
@@ -23,7 +23,6 @@ var ReactFragment = require('ReactFragment');
23 var ReactPropTypeLocations = require('ReactPropTypeLocations');
24 var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames');
25 var ReactCurrentOwner = require('ReactCurrentOwner');
26 -var ReactNativeComponent = require('ReactNativeComponent');
26
27 var getIteratorFn = require('getIteratorFn');
28 var invariant = require('invariant');
@@ -293,18 +292,10 @@ function checkPropTypes(componentName, propTypes, props, location) {
292 * @param {ReactElement} element
293 */
294 function validatePropTypes(element) {
296 - if (!(typeof element.type === 'string' ||
297 - typeof element.type === 'function')) {
298 - // This has already warned. Don't throw.
295 + var componentClass = element.type;
296 + if (typeof componentClass !== 'function') {
297 return;
298 }
301 - // Extract the component class from the element. Converts string types
302 - // to a composite class which may have propTypes.
303 - // TODO: Validating a string's propTypes is not decoupled from the
304 - // rendering target which is problematic.
305 - var componentClass = ReactNativeComponent.getComponentClassForElement(
306 - element
307 - );
299 var name = componentClass.displayName || componentClass.name;
300 if (componentClass.propTypes) {
301 checkPropTypes(
src/renderers/dom/client/findDOMNode.js
+1 -2
@@ -17,7 +17,6 @@ var ReactInstanceMap = require('ReactInstanceMap');
17 var ReactMount = require('ReactMount');
18
19 var invariant = require('invariant');
20 -var isNode = require('isNode');
20 var warning = require('warning');
21
22 /**
@@ -45,7 +44,7 @@ function findDOMNode(componentOrElement) {
44 if (componentOrElement == null) {
45 return null;
46 }
48 - if (isNode(componentOrElement)) {
47 + if (componentOrElement.nodeType === 1) {
48 return componentOrElement;
49 }
50 if (ReactInstanceMap.has(componentOrElement)) {
src/renderers/dom/shared/ReactDOMComponent.js
+4
@@ -820,6 +820,10 @@ ReactDOMComponent.Mixin = {
820 this._wrapperState = null;
821 },
822
823 + getPublicInstance: function() {
824 + return ReactMount.getNode(this._rootNodeID);
825 + },
826 +
827 };
828
829 ReactPerf.measureMethods(ReactDOMComponent, 'ReactDOMComponent', {
src/renderers/dom/shared/ReactDefaultInjection.js
-92
@@ -19,18 +19,15 @@ var EnterLeaveEventPlugin = require('EnterLeaveEventPlugin');
19 var ExecutionEnvironment = require('ExecutionEnvironment');
20 var HTMLDOMPropertyConfig = require('HTMLDOMPropertyConfig');
21 var ReactBrowserComponentMixin = require('ReactBrowserComponentMixin');
22 -var ReactClass = require('ReactClass');
22 var ReactComponentBrowserEnvironment =
23 require('ReactComponentBrowserEnvironment');
24 var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy');
25 var ReactDOMComponent = require('ReactDOMComponent');
26 var ReactDOMIDOperations = require('ReactDOMIDOperations');
27 var ReactDOMTextComponent = require('ReactDOMTextComponent');
29 -var ReactElement = require('ReactElement');
28 var ReactEventListener = require('ReactEventListener');
29 var ReactInjection = require('ReactInjection');
30 var ReactInstanceHandles = require('ReactInstanceHandles');
33 -var ReactInstanceMap = require('ReactInstanceMap');
31 var ReactMount = require('ReactMount');
32 var ReactReconcileTransaction = require('ReactReconcileTransaction');
33 var SelectEventPlugin = require('SelectEventPlugin');
@@ -38,91 +35,6 @@ var ServerReactRootIndex = require('ServerReactRootIndex');
35 var SimpleEventPlugin = require('SimpleEventPlugin');
36 var SVGDOMPropertyConfig = require('SVGDOMPropertyConfig');
37
41 -var warning = require('warning');
42 -
43 -var canDefineProperty = false;
44 -try {
45 - Object.defineProperty({}, 'test', {get: function() {}});
46 - canDefineProperty = true;
47 -} catch (e) {
48 -}
49 -
50 -var deprecatedDOMMethods = [
51 - 'isMounted', 'replaceProps', 'replaceState', 'setProps', 'setState',
52 - 'forceUpdate',
53 -];
54 -
55 -function getDeclarationErrorAddendum(domWrapperClass) {
56 - var internalInstance = ReactInstanceMap.get(domWrapperClass);
57 - var owner = internalInstance._currentElement._owner || null;
58 - if (owner) {
59 - var name = owner.getName();
60 - if (name) {
61 - return ' This DOM component was rendered by `' + name + '`.';
62 - }
63 - }
64 - return '';
65 -}
66 -
67 -function autoGenerateWrapperClass(type) {
68 - var wrapperClass = ReactClass.createClass({
69 - tagName: type.toUpperCase(),
70 - render: function() {
71 - // Copy owner down for debugging info
72 - var internalInstance = ReactInstanceMap.get(this);
73 - return new ReactElement(
74 - type,
75 - null, // key
76 - null, // ref
77 - internalInstance._currentElement._owner, // owner
78 - this._internalProps || this.props
79 - );
80 - },
81 - });
82 -
83 - if (__DEV__) {
84 - if (canDefineProperty) {
85 - Object.defineProperty(wrapperClass.prototype, 'props', {
86 - enumerable: true,
87 - set: function(props) {
88 - this._internalProps = props;
89 - },
90 - get: function() {
91 - warning(
92 - false,
93 - 'ReactDOMComponent.props: Do not access .props of a DOM ' +
94 - 'component directly; instead, recreate the props as `render` ' +
95 - 'did originally or use React.findDOMNode and read the DOM ' +
96 - 'properties/attributes directly.%s',
97 - getDeclarationErrorAddendum(this)
98 - );
99 - return this._internalProps;
100 - },
101 - });
102 -
103 - deprecatedDOMMethods.forEach(function(method) {
104 - var old = wrapperClass.prototype[method];
105 - Object.defineProperty(wrapperClass.prototype, method, {
106 - enumerable: true,
107 - get: function() {
108 - warning(
109 - false,
110 - 'ReactDOMComponent.%s(): Do not access .%s() of a DOM ' +
111 - 'component.%s',
112 - method,
113 - method,
114 - getDeclarationErrorAddendum(this)
115 - );
116 - return old;
117 - },
118 - });
119 - });
120 - }
121 - }
122 -
123 - return wrapperClass;
124 -}
125 -
38 var alreadyInjected = false;
39
40 function inject() {
@@ -165,10 +77,6 @@ function inject() {
77 ReactDOMTextComponent
78 );
79
168 - ReactInjection.NativeComponent.injectAutoWrapper(
169 - autoGenerateWrapperClass
170 - );
171 -
80 ReactInjection.Class.injectMixin(ReactBrowserComponentMixin);
81
82 ReactInjection.DOMProperty.injectDOMPropertyConfig(HTMLDOMPropertyConfig);
src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js
+3 -3
@@ -805,12 +805,12 @@ describe('ReactDOMComponent', function() {
805 it('warns on invalid nesting at root', () => {
806 spyOn(console, 'error');
807 var p = document.createElement('p');
808 - React.render(<tr />, p);
808 + React.render(<span><p /></span>, p);
809
810 expect(console.error.calls.length).toBe(1);
811 expect(console.error.calls[0].args[0]).toBe(
812 - 'Warning: validateDOMNesting(...): <tr> cannot appear as a child of ' +
813 - '<p>. See p > tr.'
812 + 'Warning: validateDOMNesting(...): <p> cannot appear as a descendant ' +
813 + 'of <p>. See p > ... > p.'
814 );
815 });
816
src/renderers/shared/reconciler/ReactCompositeComponent.js
+7 -20
@@ -15,7 +15,6 @@ var ReactComponentEnvironment = require('ReactComponentEnvironment');
15 var ReactCurrentOwner = require('ReactCurrentOwner');
16 var ReactElement = require('ReactElement');
17 var ReactInstanceMap = require('ReactInstanceMap');
18 -var ReactNativeComponent = require('ReactNativeComponent');
18 var ReactPerf = require('ReactPerf');
19 var ReactPropTypeLocations = require('ReactPropTypeLocations');
20 var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames');
@@ -123,9 +122,7 @@ var ReactCompositeComponentMixin = {
122 var publicProps = this._processProps(this._currentElement.props);
123 var publicContext = this._processContext(context);
124
126 - var Component = ReactNativeComponent.getComponentClassForElement(
127 - this._currentElement
128 - );
125 + var Component = this._currentElement.type;
126
127 // Initialize the public class
128 var inst = new Component(publicProps, publicContext);
@@ -235,8 +232,7 @@ var ReactCompositeComponentMixin = {
232 var renderedElement = this._renderValidatedComponent();
233
234 this._renderedComponent = this._instantiateReactComponent(
238 - renderedElement,
239 - this._currentElement.type // The wrapping type
235 + renderedElement
236 );
237
238 var markup = ReactReconciler.mountComponent(
@@ -304,9 +300,7 @@ var ReactCompositeComponentMixin = {
300 */
301 _maskContext: function(context) {
302 var maskedContext = null;
307 - var Component = ReactNativeComponent.getComponentClassForElement(
308 - this._currentElement
309 - );
303 + var Component = this._currentElement.type;
304 var contextTypes = Component.contextTypes;
305 if (!contextTypes) {
306 return emptyObject;
@@ -329,9 +323,7 @@ var ReactCompositeComponentMixin = {
323 _processContext: function(context) {
324 var maskedContext = this._maskContext(context);
325 if (__DEV__) {
332 - var Component = ReactNativeComponent.getComponentClassForElement(
333 - this._currentElement
334 - );
326 + var Component = this._currentElement.type;
327 if (Component.contextTypes) {
328 this._checkPropTypes(
329 Component.contextTypes,
@@ -349,9 +341,7 @@ var ReactCompositeComponentMixin = {
341 * @private
342 */
343 _processChildContext: function(currentContext) {
352 - var Component = ReactNativeComponent.getComponentClassForElement(
353 - this._currentElement
354 - );
344 + var Component = this._currentElement.type;
345 var inst = this._instance;
346 var childContext = inst.getChildContext && inst.getChildContext();
347 if (childContext) {
@@ -392,9 +382,7 @@ var ReactCompositeComponentMixin = {
382 */
383 _processProps: function(newProps) {
384 if (__DEV__) {
395 - var Component = ReactNativeComponent.getComponentClassForElement(
396 - this._currentElement
397 - );
385 + var Component = this._currentElement.type;
386 if (Component.propTypes) {
387 this._checkPropTypes(
388 Component.propTypes,
@@ -695,8 +683,7 @@ var ReactCompositeComponentMixin = {
683 ReactReconciler.unmountComponent(prevComponentInstance);
684
685 this._renderedComponent = this._instantiateReactComponent(
698 - nextRenderedElement,
699 - this._currentElement.type
686 + nextRenderedElement
687 );
688 var nextMarkup = ReactReconciler.mountComponent(
689 this._renderedComponent,
src/renderers/shared/reconciler/ReactNativeComponent.js
-5
@@ -36,11 +36,6 @@ var ReactNativeComponentInjection = {
36 injectComponentClasses: function(componentClasses) {
37 assign(tagToComponentClass, componentClasses);
38 },
39 - // Temporary hack since we expect DOM refs to behave like composites,
40 - // for this release.
41 - injectAutoWrapper: function(wrapperFactory) {
42 - autoGenerateWrapperClass = wrapperFactory;
43 - },
39 };
40
41 /**
src/renderers/shared/reconciler/__tests__/ReactInstanceHandles-test.js
+5 -6
@@ -12,7 +12,6 @@
12 'use strict';
13
14 var React = require('React');
15 -var ReactInstanceMap = require('ReactInstanceMap');
15 var ReactTestUtils = require('ReactTestUtils');
16 var ReactMount = require('ReactMount');
17
@@ -63,11 +62,11 @@ describe('ReactInstanceHandles', function() {
62 });
63 }
64
66 - function getNodeID(instance) {
67 - if (instance === null) {
65 + function getNodeID(el) {
66 + if (el === null) {
67 return '';
68 }
70 - return ReactInstanceMap.get(instance)._rootNodeID;
69 + return el.getAttribute('data-reactid');
70 }
71
72 beforeEach(function() {
@@ -389,8 +388,8 @@ describe('ReactInstanceHandles', function() {
388 // Common ancestor with grandparent is the grandparent.
389 {
390 one: parent.refs.P_P1_C1.refs.DIV_1,
392 - two: parent.refs.P_P1_C1,
393 - com: parent.refs.P_P1_C1,
391 + two: parent.refs.P_P1,
392 + com: parent.refs.P_P1,
393 },
394 // Grantparent across subcomponent boundaries.
395 {
src/renderers/shared/reconciler/__tests__/ReactMultiChildReconcile-test.js
-1
@@ -89,7 +89,6 @@ var FriendsStatusDisplay = React.createClass({
89 var statusDisplays =
90 ReactInstanceMap.get(this)
91 ._renderedComponent
92 - ._renderedComponent
92 ._renderedChildren;
93 for (name in statusDisplays) {
94 var child = statusDisplays[name];
src/renderers/shared/reconciler/instantiateReactComponent.js
+2 -7
@@ -60,11 +60,10 @@ function isInternalComponentType(type) {
60 * Given a ReactNode, create an instance that will actually be mounted.
61 *
62 * @param {ReactNode} node
63 - * @param {*} parentCompositeType The composite type that resolved this.
63 * @return {object} A new instance of the element's constructor.
64 * @protected
65 */
67 -function instantiateReactComponent(node, parentCompositeType) {
66 +function instantiateReactComponent(node) {
67 var instance;
68
69 if (node === null || node === false) {
@@ -83,12 +82,8 @@ function instantiateReactComponent(node, parentCompositeType) {
82 );
83
84 // Special case string values
86 - if (parentCompositeType === element.type &&
87 - typeof element.type === 'string') {
88 - // Avoid recursion if the wrapper renders itself.
85 + if (typeof element.type === 'string') {
86 instance = ReactNativeComponent.createInternalComponent(element);
90 - // All native components are currently wrapped in a composite so we're
91 - // safe to assume that this is what we should instantiate.
87 } else if (isInternalComponentType(element.type)) {
88 // This is temporarily available for custom components that are not string
89 // represenations. I.e. ART. Once those are updated to use the string
src/test/ReactTestUtils.js
+8 -5
@@ -45,7 +45,7 @@ function findAllInRenderedTreeInternal(inst, test) {
45 var publicInst = inst.getPublicInstance()
46 var ret = test(publicInst) ? [publicInst] : [];
47 if (ReactTestUtils.isDOMComponent(publicInst)) {
48 - var renderedChildren = inst._renderedComponent._renderedChildren;
48 + var renderedChildren = inst._renderedChildren;
49 var key;
50 for (key in renderedChildren) {
51 if (!renderedChildren.hasOwnProperty(key)) {
@@ -96,7 +96,7 @@ var ReactTestUtils = {
96 isDOMComponent: function(inst) {
97 // TODO: Fix this heuristic. It's just here because composites can currently
98 // pretend to be DOM components.
99 - return !!(inst && inst.tagName && inst.getDOMNode);
99 + return !!(inst && inst.nodeType === 1 && inst.tagName);
100 },
101
102 isDOMComponentElement: function(inst) {
@@ -116,13 +116,15 @@ var ReactTestUtils = {
116 },
117
118 isCompositeComponentWithType: function(inst, type) {
119 + if (!ReactTestUtils.isCompositeComponent(inst)) {
120 + return false;
121 + }
122 var internalInstance = ReactInstanceMap.get(inst);
123 var constructor = internalInstance
124 ._currentElement
125 .type;
126
124 - return !!(ReactTestUtils.isCompositeComponent(inst) &&
125 - (constructor === type));
127 + return (constructor === type);
128 },
129
130 isCompositeComponentElement: function(inst) {
@@ -256,7 +258,8 @@ var ReactTestUtils = {
258 );
259 if (all.length !== 1) {
260 throw new Error(
259 - 'Did not find exactly one match for componentType:' + componentType
261 + 'Did not find exactly one match for componentType:' + componentType +
262 + ' (found ' + all.length + ')'
263 );
264 }
265 return all[0];
src/test/reactComponentExpect.js
+3 -3
@@ -85,7 +85,7 @@ assign(reactComponentExpectInternal.prototype, {
85 // change soon.
86 this.toBeDOMComponent();
87 var renderedChildren =
88 - this._instance._renderedComponent._renderedChildren || {};
88 + this._instance._renderedChildren || {};
89 for (var name in renderedChildren) {
90 if (!renderedChildren.hasOwnProperty(name)) {
91 continue;
@@ -101,7 +101,7 @@ assign(reactComponentExpectInternal.prototype, {
101
102 toBeDOMComponentWithChildCount: function(count) {
103 this.toBeDOMComponent();
104 - var renderedChildren = this._instance._renderedComponent._renderedChildren;
104 + var renderedChildren = this._instance._renderedChildren;
105 expect(renderedChildren).toBeTruthy();
106 expect(Object.keys(renderedChildren).length).toBe(count);
107 return this;
@@ -109,7 +109,7 @@ assign(reactComponentExpectInternal.prototype, {
109
110 toBeDOMComponentWithNoChildren: function() {
111 this.toBeDOMComponent();
112 - expect(this._instance._renderedComponent._renderedChildren).toBeFalsy();
112 + expect(this._instance._renderedChildren).toBeFalsy();
113 return this;
114 },
115