From 382be4e9e99e523f2e42dc1734e8a97a56e2b1e4 Mon Sep 17 00:00:00 2001 From: Ben Alpert Date: Sat, 12 Apr 2014 15:32:15 -0700 Subject: [PATCH] Improve error for nested render calls In the future we could consider wrapping the entire public API (renderComponent, setProps, setState, etc) in this check but this should do for now. Test Plan: grunt test --- src/core/ReactCompositeComponent.js | 11 +++++++++ .../__tests__/ReactCompositeComponent-test.js | 23 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/core/ReactCompositeComponent.js b/src/core/ReactCompositeComponent.js index f6681d44f7..f6af832e67 100644 --- a/src/core/ReactCompositeComponent.js +++ b/src/core/ReactCompositeComponent.js @@ -1164,6 +1164,17 @@ var ReactCompositeComponentMixin = { 'ReactCompositeComponent', '_renderValidatedComponent', function() { + // We set ReactCurrentOwner.current back to null at the end of this + // function, so it should be null right now. If it's not, later code may + // give confusing errors. + invariant( + ReactCurrentOwner.current == null, + '%s.render(): Render methods should be a pure function of props and ' + + 'state; triggering nested component updates from render is not ' + + 'allowed. If necessary, trigger nested updates in ' + + 'componentDidUpdate.', + this.constructor.displayName || 'ReactCompositeComponent' + ); var renderedComponent; var previousContext = ReactContext.current; ReactContext.current = this._processChildContext( diff --git a/src/core/__tests__/ReactCompositeComponent-test.js b/src/core/__tests__/ReactCompositeComponent-test.js index add279580f..6994a7a0b4 100644 --- a/src/core/__tests__/ReactCompositeComponent-test.js +++ b/src/core/__tests__/ReactCompositeComponent-test.js @@ -1345,4 +1345,27 @@ describe('ReactCompositeComponent', function() { expect(console.warn.argsForCall.length).toBe(0); }); + it('should disallow nested render calls', function() { + var Inner = React.createClass({ + render: function() { + return
; + } + }); + var Outer = React.createClass({ + render: function() { + ReactTestUtils.renderIntoDocument(); + return
; + } + }); + + expect(() => { + ReactTestUtils.renderIntoDocument(); + }).toThrow( + 'Invariant Violation: Inner.render(): Render methods should be a pure ' + + 'function of props and state; triggering nested component updates ' + + 'from render is not allowed. If necessary, trigger nested updates in ' + + 'componentDidUpdate.' + ); + }); + });