From 428ef03bbba526032defe2a60252e9e0ca0d15e4 Mon Sep 17 00:00:00 2001 From: jim Date: Tue, 9 Feb 2016 12:07:06 -0800 Subject: [PATCH] Enable module pattern. --- .../reconciler/ReactCompositeComponent.js | 38 ++++++++++++++++--- .../__tests__/ReactCompositeComponent-test.js | 15 ++++++++ .../__tests__/ReactEmptyComponent-test.js | 2 +- .../__tests__/ReactStatelessComponent-test.js | 8 ++-- 4 files changed, 52 insertions(+), 11 deletions(-) diff --git a/src/renderers/shared/reconciler/ReactCompositeComponent.js b/src/renderers/shared/reconciler/ReactCompositeComponent.js index 8914fb6eaf..881028ff5d 100644 --- a/src/renderers/shared/reconciler/ReactCompositeComponent.js +++ b/src/renderers/shared/reconciler/ReactCompositeComponent.js @@ -44,16 +44,20 @@ function StatelessComponent(Component) { StatelessComponent.prototype.render = function() { var Component = ReactInstanceMap.get(this)._currentElement.type; var element = Component(this.props, this.context, this.updater); + warnIfInvalidElement(Component, element); + return element; +}; + +function warnIfInvalidElement(Component, element) { if (__DEV__) { warning( element === null || element === false || ReactElement.isValidElement(element), - '%s must be a class extending React.Component or be a stateless ' + - 'function that returns a valid React element.', + '%s(...): A valid React element (or null) must be returned. You may have ' + + 'returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component' ); } - return element; -}; +} /** * ------------------ The Life-Cycle of a Composite Component ------------------ @@ -168,7 +172,29 @@ var ReactCompositeComponentMixin = { inst = new Component(publicProps, publicContext, ReactUpdateQueue); } } else { - inst = new StatelessComponent(Component); + if (__DEV__) { + ReactCurrentOwner.current = this; + try { + inst = Component(publicProps, publicContext, ReactUpdateQueue); + } finally { + ReactCurrentOwner.current = null; + } + } else { + inst = Component(publicProps, publicContext, ReactUpdateQueue); + } + if (inst == null || inst.render == null) { + renderedElement = inst; + warnIfInvalidElement(Component, renderedElement); + invariant( + inst === null || + inst === false || + ReactElement.isValidElement(inst), + '%s(...): A valid React element (or null) must be returned. You may have ' + + 'returned undefined, an array or some other invalid object.', + Component.displayName || Component.name || 'Component' + ); + inst = new StatelessComponent(Component); + } } if (__DEV__) { @@ -869,7 +895,7 @@ var ReactCompositeComponentMixin = { // TODO: An `isValidNode` function would probably be more appropriate renderedComponent === null || renderedComponent === false || ReactElement.isValidElement(renderedComponent), - '%s.render(): A valid ReactComponent must be returned. You may have ' + + '%s.render(): A valid React element (or null) must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', this.getName() || 'ReactCompositeComponent' ); diff --git a/src/renderers/shared/reconciler/__tests__/ReactCompositeComponent-test.js b/src/renderers/shared/reconciler/__tests__/ReactCompositeComponent-test.js index 696786bea1..456b013258 100644 --- a/src/renderers/shared/reconciler/__tests__/ReactCompositeComponent-test.js +++ b/src/renderers/shared/reconciler/__tests__/ReactCompositeComponent-test.js @@ -72,6 +72,21 @@ describe('ReactCompositeComponent', function() { spyOn(console, 'error'); }); + it('should support module pattern components', function() { + function Child({test}) { + return { + render() { + return
{test}
; + }, + }; + } + + var el = document.createElement('div'); + ReactDOM.render(, el); + + expect(el.textContent).toBe('test'); + }); + it('should support rendering to different child types over time', function() { var instance = ; instance = ReactTestUtils.renderIntoDocument(instance); diff --git a/src/renderers/shared/reconciler/__tests__/ReactEmptyComponent-test.js b/src/renderers/shared/reconciler/__tests__/ReactEmptyComponent-test.js index 98d5354e20..406e18e2a1 100644 --- a/src/renderers/shared/reconciler/__tests__/ReactEmptyComponent-test.js +++ b/src/renderers/shared/reconciler/__tests__/ReactEmptyComponent-test.js @@ -79,7 +79,7 @@ describe('ReactEmptyComponent', function() { expect(function() { ReactTestUtils.renderIntoDocument(); }).toThrow( - 'Component.render(): A valid ReactComponent must be returned. You may ' + + 'Component.render(): A valid React element (or null) must be returned. You may ' + 'have returned undefined, an array or some other invalid object.' ); }); diff --git a/src/renderers/shared/reconciler/__tests__/ReactStatelessComponent-test.js b/src/renderers/shared/reconciler/__tests__/ReactStatelessComponent-test.js index 5c1795e5a4..8e0c8ac492 100644 --- a/src/renderers/shared/reconciler/__tests__/ReactStatelessComponent-test.js +++ b/src/renderers/shared/reconciler/__tests__/ReactStatelessComponent-test.js @@ -108,8 +108,8 @@ describe('ReactStatelessComponent', function() { }).toThrow(); expect(console.error.calls.length).toBe(1); expect(console.error.argsForCall[0][0]).toContain( - 'NotAComponent must be a class extending React.Component or be a stateless ' + - 'function that returns a valid React element.' + 'NotAComponent(...): A valid React element (or null) must be returned. '+ + 'You may have returned undefined, an array or some other invalid object.' ); }); @@ -238,8 +238,8 @@ describe('ReactStatelessComponent', function() { }).toThrow(); // has no method 'render' expect(console.error.calls.length).toBe(1); expect(console.error.argsForCall[0][0]).toContain( - 'Warning: NotAComponent must be a class extending React.Component or be a stateless ' + - 'function that returns a valid React element.' + 'NotAComponent(...): A valid React element (or null) must be returned. You may ' + + 'have returned undefined, an array or some other invalid object.' ); }); });