From 7036e396af1163828c249b6d4ae2bb78700c22f4 Mon Sep 17 00:00:00 2001 From: Dean Brophy Date: Wed, 1 Nov 2017 15:01:24 -0600 Subject: [PATCH] Constructor error message (#11395) * Constructor test and fix complete * Linters and prettier run * Remove unnecessary checks * Update error message * Updat unit test * prettier * Tweak the check to be more specific * Move tests to ReactCompositeComponent-test * add error call count and remove line --- .../__tests__/ReactCompositeComponent-test.js | 39 +++++++++++++++++++ .../src/ReactFiberClassComponent.js | 25 +++++++++--- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js index 10b4b73c335c9..af7688573b6cd 100644 --- a/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactCompositeComponent-test.js @@ -1533,4 +1533,43 @@ describe('ReactCompositeComponent', () => { ReactTestUtils.renderIntoDocument(); expect(mockArgs.length).toEqual(0); }); + + it('should return a meaningful warning when constructor is returned', () => { + spyOn(console, 'error'); + class RenderTextInvalidConstructor extends React.Component { + constructor(props) { + super(props); + return {something: false}; + } + + render() { + return
; + } + } + + expect(function() { + ReactTestUtils.renderIntoDocument(); + }).toThrow(); + + expectDev(console.error.calls.count()).toBe(1); + expectDev(console.error.calls.mostRecent().args[0]).toBe( + 'Warning: RenderTextInvalidConstructor(...): No `render` method found on the returned component instance: ' + + 'did you accidentally return an object from the constructor?', + ); + }); + + it('should return error if render is not defined', () => { + spyOn(console, 'error'); + class RenderTestUndefinedRender extends React.Component {} + + expect(function() { + ReactTestUtils.renderIntoDocument(); + }).toThrow(); + + expectDev(console.error.calls.count()).toBe(1); + expectDev(console.error.calls.mostRecent().args[0]).toBe( + 'Warning: RenderTestUndefinedRender(...): No `render` method found on the returned ' + + 'component instance: you may have forgotten to define `render`.', + ); + }); }); diff --git a/packages/react-reconciler/src/ReactFiberClassComponent.js b/packages/react-reconciler/src/ReactFiberClassComponent.js index 2a1e9a64ee3b9..50855e4242d4a 100644 --- a/packages/react-reconciler/src/ReactFiberClassComponent.js +++ b/packages/react-reconciler/src/ReactFiberClassComponent.js @@ -202,12 +202,25 @@ module.exports = function( if (__DEV__) { const name = getComponentName(workInProgress); const renderPresent = instance.render; - warning( - renderPresent, - '%s(...): No `render` method found on the returned component ' + - 'instance: you may have forgotten to define `render`.', - name, - ); + + if (!renderPresent) { + if (type.prototype && typeof type.prototype.render === 'function') { + warning( + false, + '%s(...): No `render` method found on the returned component ' + + 'instance: did you accidentally return an object from the constructor?', + name, + ); + } else { + warning( + false, + '%s(...): No `render` method found on the returned component ' + + 'instance: you may have forgotten to define `render`.', + name, + ); + } + } + const noGetInitialStateOnES6 = !instance.getInitialState || instance.getInitialState.isReactClassApproved ||