From 83644185f4388834c0c482c7522a5f2f476d84a2 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Wed, 30 Sep 2015 18:28:49 -0700 Subject: [PATCH] isReactClass -> .prototype.isReactComponent Put the flag on the prototype instead to help certain limited forms of class extensions that doesn't properly transfer static properties. Fixes #4836 --- src/isomorphic/classic/class/ReactClass.js | 1 - src/isomorphic/modern/class/ReactComponent.js | 2 +- src/renderers/dom/client/ReactMount.js | 2 +- .../reconciler/ReactCompositeComponent.js | 2 +- .../__tests__/ReactCompositeComponent-test.js | 30 +++++++++++++++++++ 5 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/isomorphic/classic/class/ReactClass.js b/src/isomorphic/classic/class/ReactClass.js index b4248c62f7..b335a07344 100644 --- a/src/isomorphic/classic/class/ReactClass.js +++ b/src/isomorphic/classic/class/ReactClass.js @@ -847,7 +847,6 @@ var ReactClass = { }; Constructor.prototype = new ReactClassComponent(); Constructor.prototype.constructor = Constructor; - Constructor.isReactClass = {}; injectedMixins.forEach( mixSpecIntoComponent.bind(null, Constructor) diff --git a/src/isomorphic/modern/class/ReactComponent.js b/src/isomorphic/modern/class/ReactComponent.js index 3390ff161b..f99cb0385c 100644 --- a/src/isomorphic/modern/class/ReactComponent.js +++ b/src/isomorphic/modern/class/ReactComponent.js @@ -29,7 +29,7 @@ function ReactComponent(props, context, updater) { this.updater = updater || ReactNoopUpdateQueue; } -ReactComponent.isReactClass = {}; +ReactComponent.prototype.isReactComponent = {}; /** * Sets a subset of the state. Always use this to mutate diff --git a/src/renderers/dom/client/ReactMount.js b/src/renderers/dom/client/ReactMount.js index f536bbb6de..67ff78d0da 100644 --- a/src/renderers/dom/client/ReactMount.js +++ b/src/renderers/dom/client/ReactMount.js @@ -412,7 +412,7 @@ function findFirstReactDOMImpl(node) { * here. */ var TopLevelWrapper = function() {}; -TopLevelWrapper.isReactClass = {}; +TopLevelWrapper.prototype.isReactComponent = {}; if (__DEV__) { TopLevelWrapper.displayName = 'TopLevelWrapper'; } diff --git a/src/renderers/shared/reconciler/ReactCompositeComponent.js b/src/renderers/shared/reconciler/ReactCompositeComponent.js index b96ece5133..09be6c0532 100644 --- a/src/renderers/shared/reconciler/ReactCompositeComponent.js +++ b/src/renderers/shared/reconciler/ReactCompositeComponent.js @@ -176,7 +176,7 @@ var ReactCompositeComponentMixin = { // We support ES6 inheriting from React.Component, the module pattern, // and stateless components, but not ES6 classes that don't extend warning( - Component.isReactClass || + (Component.prototype && Component.prototype.isReactComponent) || !canInstantiate || !(inst instanceof Component), '%s(...): React component classes must extend React.Component.', diff --git a/src/renderers/shared/reconciler/__tests__/ReactCompositeComponent-test.js b/src/renderers/shared/reconciler/__tests__/ReactCompositeComponent-test.js index 929d3e70eb..5d46c433f1 100644 --- a/src/renderers/shared/reconciler/__tests__/ReactCompositeComponent-test.js +++ b/src/renderers/shared/reconciler/__tests__/ReactCompositeComponent-test.js @@ -1211,5 +1211,35 @@ describe('ReactCompositeComponent', function() { expect(console.error.calls.length).toBe(0); }); + it('should warn when a class does not extend React.Component', function() { + + var container = document.createElement('div'); + + class Foo { + render() { + return ; + } + } + + function Bar() { } + Bar.prototype = Object.create(React.Component.prototype); + Bar.prototype.render = function() { + return ; + }; + + expect(console.error.calls.length).toBe(0); + + ReactDOM.render(, container); + + expect(console.error.calls.length).toBe(0); + + ReactDOM.render(, container); + + expect(console.error.calls.length).toBe(1); + expect(console.error.argsForCall[0][0]).toContain( + 'React component classes must extend React.Component' + ); + + }); });