From 650fa58ab9990be74596899a0cb8212d6da3863f Mon Sep 17 00:00:00 2001 From: Bradley Spaulding Date: Tue, 22 Sep 2015 14:27:17 -0700 Subject: [PATCH 1/5] Composite component throws on attaching ref to stateless component #4939 --- .../shared/reconciler/ReactCompositeComponent.js | 4 +++- .../__tests__/ReactStatelessComponent-test.js | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/renderers/shared/reconciler/ReactCompositeComponent.js b/src/renderers/shared/reconciler/ReactCompositeComponent.js index b96ece5133cfe..c4729e39ea30c 100644 --- a/src/renderers/shared/reconciler/ReactCompositeComponent.js +++ b/src/renderers/shared/reconciler/ReactCompositeComponent.js @@ -808,8 +808,10 @@ var ReactCompositeComponentMixin = { attachRef: function(ref, component) { var inst = this.getPublicInstance(); invariant(inst != null, 'Stateless function components cannot have refs.'); + var componentInstance = component.getPublicInstance(); + invariant(componentInstance != null, 'Stateless function components cannot be given refs.'); var refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs; - refs[ref] = component.getPublicInstance(); + refs[ref] = componentInstance; }, /** diff --git a/src/renderers/shared/reconciler/__tests__/ReactStatelessComponent-test.js b/src/renderers/shared/reconciler/__tests__/ReactStatelessComponent-test.js index c94c60f8274b3..4c07358a2a440 100644 --- a/src/renderers/shared/reconciler/__tests__/ReactStatelessComponent-test.js +++ b/src/renderers/shared/reconciler/__tests__/ReactStatelessComponent-test.js @@ -125,6 +125,20 @@ describe('ReactStatelessComponent', function() { ); }); + it('should throw when given a ref', function() { + var Parent = React.createClass({ + render: function() { + return ; + }, + }); + + expect(function() { + ReactTestUtils.renderIntoDocument(); + }).toThrow( + 'Invariant Violation: Stateless function components cannot be given refs.' + ); + }); + it('should provide a null ref', function() { function Child() { return
; From 8b4663d722fc50f602c762ce75881faad3619b83 Mon Sep 17 00:00:00 2001 From: Bradley Spaulding Date: Thu, 24 Sep 2015 11:46:41 -0700 Subject: [PATCH 2/5] Renamed componentInstance to publicComponentInstance --- src/renderers/shared/reconciler/ReactCompositeComponent.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/renderers/shared/reconciler/ReactCompositeComponent.js b/src/renderers/shared/reconciler/ReactCompositeComponent.js index c4729e39ea30c..5d6a517cd2174 100644 --- a/src/renderers/shared/reconciler/ReactCompositeComponent.js +++ b/src/renderers/shared/reconciler/ReactCompositeComponent.js @@ -808,10 +808,10 @@ var ReactCompositeComponentMixin = { attachRef: function(ref, component) { var inst = this.getPublicInstance(); invariant(inst != null, 'Stateless function components cannot have refs.'); - var componentInstance = component.getPublicInstance(); - invariant(componentInstance != null, 'Stateless function components cannot be given refs.'); + var publicComponentInstance = component.getPublicInstance(); + invariant(publicComponentInstance != null, 'Stateless function components cannot be given refs.'); var refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs; - refs[ref] = componentInstance; + refs[ref] = publicComponentInstance; }, /** From af7911814835891522d0d910428eb85e005ec92b Mon Sep 17 00:00:00 2001 From: Bradley Spaulding Date: Thu, 24 Sep 2015 11:52:46 -0700 Subject: [PATCH 3/5] attachRef to a stateless component warns instead of throwing #4939 --- .../shared/reconciler/ReactCompositeComponent.js | 2 +- .../__tests__/ReactStatelessComponent-test.js | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/renderers/shared/reconciler/ReactCompositeComponent.js b/src/renderers/shared/reconciler/ReactCompositeComponent.js index 5d6a517cd2174..90715744df7c2 100644 --- a/src/renderers/shared/reconciler/ReactCompositeComponent.js +++ b/src/renderers/shared/reconciler/ReactCompositeComponent.js @@ -809,7 +809,7 @@ var ReactCompositeComponentMixin = { var inst = this.getPublicInstance(); invariant(inst != null, 'Stateless function components cannot have refs.'); var publicComponentInstance = component.getPublicInstance(); - invariant(publicComponentInstance != null, 'Stateless function components cannot be given refs.'); + warning(publicComponentInstance != null, 'Stateless function components cannot be given refs.'); var refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs; refs[ref] = publicComponentInstance; }, diff --git a/src/renderers/shared/reconciler/__tests__/ReactStatelessComponent-test.js b/src/renderers/shared/reconciler/__tests__/ReactStatelessComponent-test.js index 4c07358a2a440..c7db9123b151e 100644 --- a/src/renderers/shared/reconciler/__tests__/ReactStatelessComponent-test.js +++ b/src/renderers/shared/reconciler/__tests__/ReactStatelessComponent-test.js @@ -125,17 +125,19 @@ describe('ReactStatelessComponent', function() { ); }); - it('should throw when given a ref', function() { + it('should warn when given a ref', function() { + spyOn(console, 'error'); + var Parent = React.createClass({ render: function() { return ; }, }); + ReactTestUtils.renderIntoDocument(); - expect(function() { - ReactTestUtils.renderIntoDocument(); - }).toThrow( - 'Invariant Violation: Stateless function components cannot be given refs.' + expect(console.error.argsForCall.length).toBe(1); + expect(console.error.argsForCall[0][0]).toContain( + 'Stateless function components cannot be given refs.' ); }); From 63cfcca74eb9805720968e69b18c09f4c80e188d Mon Sep 17 00:00:00 2001 From: Bradley Spaulding Date: Fri, 25 Sep 2015 16:21:00 -0700 Subject: [PATCH 4/5] Updated stateless ref warning message with more info --- .../shared/reconciler/ReactCompositeComponent.js | 11 ++++++++++- .../__tests__/ReactStatelessComponent-test.js | 5 ++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/renderers/shared/reconciler/ReactCompositeComponent.js b/src/renderers/shared/reconciler/ReactCompositeComponent.js index 90715744df7c2..e7f220fe1b4ba 100644 --- a/src/renderers/shared/reconciler/ReactCompositeComponent.js +++ b/src/renderers/shared/reconciler/ReactCompositeComponent.js @@ -809,7 +809,16 @@ var ReactCompositeComponentMixin = { var inst = this.getPublicInstance(); invariant(inst != null, 'Stateless function components cannot have refs.'); var publicComponentInstance = component.getPublicInstance(); - warning(publicComponentInstance != null, 'Stateless function components cannot be given refs.'); + var componentName = component && component.getName ? + component.getName() : 'a component'; + warning(publicComponentInstance != null, + 'Stateless function components cannot be given refs ' + + '(See ref "%s" in %s created by %s). ' + + 'Attempts to access this ref will fail.', + ref, + componentName, + this.getName() + ); var refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs; refs[ref] = publicComponentInstance; }, diff --git a/src/renderers/shared/reconciler/__tests__/ReactStatelessComponent-test.js b/src/renderers/shared/reconciler/__tests__/ReactStatelessComponent-test.js index c7db9123b151e..3f703b3cd4fa1 100644 --- a/src/renderers/shared/reconciler/__tests__/ReactStatelessComponent-test.js +++ b/src/renderers/shared/reconciler/__tests__/ReactStatelessComponent-test.js @@ -129,6 +129,7 @@ describe('ReactStatelessComponent', function() { spyOn(console, 'error'); var Parent = React.createClass({ + displayName: 'Parent', render: function() { return ; }, @@ -137,7 +138,9 @@ describe('ReactStatelessComponent', function() { expect(console.error.argsForCall.length).toBe(1); expect(console.error.argsForCall[0][0]).toContain( - 'Stateless function components cannot be given refs.' + 'Stateless function components cannot be given refs ' + + '(See ref "stateless" in StatelessComponent created by Parent). ' + + 'Attempts to access this ref will fail.' ); }); From c6a3eb14db57e3663f749cd288288640f4f2d59d Mon Sep 17 00:00:00 2001 From: Bradley Spaulding Date: Mon, 5 Oct 2015 21:44:42 -0700 Subject: [PATCH 5/5] Wrapping StatelessComponent ref warning in __DEV__ block --- .../reconciler/ReactCompositeComponent.js | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/renderers/shared/reconciler/ReactCompositeComponent.js b/src/renderers/shared/reconciler/ReactCompositeComponent.js index e7f220fe1b4ba..199a4ebecbfab 100644 --- a/src/renderers/shared/reconciler/ReactCompositeComponent.js +++ b/src/renderers/shared/reconciler/ReactCompositeComponent.js @@ -809,16 +809,18 @@ var ReactCompositeComponentMixin = { var inst = this.getPublicInstance(); invariant(inst != null, 'Stateless function components cannot have refs.'); var publicComponentInstance = component.getPublicInstance(); - var componentName = component && component.getName ? - component.getName() : 'a component'; - warning(publicComponentInstance != null, - 'Stateless function components cannot be given refs ' + - '(See ref "%s" in %s created by %s). ' + - 'Attempts to access this ref will fail.', - ref, - componentName, - this.getName() - ); + if (__DEV__) { + var componentName = component && component.getName ? + component.getName() : 'a component'; + warning(publicComponentInstance != null, + 'Stateless function components cannot be given refs ' + + '(See ref "%s" in %s created by %s). ' + + 'Attempts to access this ref will fail.', + ref, + componentName, + this.getName() + ); + } var refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs; refs[ref] = publicComponentInstance; },