From 2854eb968ca629ec0c0f70c41cfddc7e21bc844c Mon Sep 17 00:00:00 2001 From: Brandon Dail Date: Wed, 13 Jul 2016 10:23:13 -0500 Subject: [PATCH 1/3] Failing test case for functional refs on SFCs2 --- .../__tests__/ReactStatelessComponent-test.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/renderers/shared/stack/reconciler/__tests__/ReactStatelessComponent-test.js b/src/renderers/shared/stack/reconciler/__tests__/ReactStatelessComponent-test.js index 8577ca180e688..59d1e117ed6ae 100644 --- a/src/renderers/shared/stack/reconciler/__tests__/ReactStatelessComponent-test.js +++ b/src/renderers/shared/stack/reconciler/__tests__/ReactStatelessComponent-test.js @@ -146,7 +146,19 @@ describe('ReactStatelessComponent', () => { ); }); - it('should warn when given a ref', () => { + it('should warn for functional refs in pure functions', function() { + spyOn(console, 'error'); + function Child() { + return
{}} />; + } + ReactTestUtils.renderIntoDocument(); + expect(console.error.calls.count()).toBe(1); + expect(console.error.calls.argsFor(0)[0]).toContain( + 'Stateless function components cannot have refs.' + ); + }); + + it('should warn when given a ref', function() { spyOn(console, 'error'); class Parent extends React.Component { From b6aaa928e9e1db5b6be26d33e2d93d4babe6f6e9 Mon Sep 17 00:00:00 2001 From: Brandon Dail Date: Wed, 13 Jul 2016 10:26:38 -0500 Subject: [PATCH 2/3] Warn if a function is passed to ref on an SFC --- src/renderers/shared/stack/reconciler/ReactRef.js | 8 +++++++- .../reconciler/__tests__/ReactStatelessComponent-test.js | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/renderers/shared/stack/reconciler/ReactRef.js b/src/renderers/shared/stack/reconciler/ReactRef.js index a7350cc6a8a73..64cfd15af6894 100644 --- a/src/renderers/shared/stack/reconciler/ReactRef.js +++ b/src/renderers/shared/stack/reconciler/ReactRef.js @@ -13,6 +13,7 @@ 'use strict'; var ReactOwner = require('ReactOwner'); +var warning = require('warning'); import type { ReactInstance } from 'ReactInstanceType'; import type { ReactElement } from 'ReactElementType'; @@ -21,7 +22,12 @@ var ReactRef = {}; function attachRef(ref, component, owner) { if (typeof ref === 'function') { - ref(component.getPublicInstance()); + var instance = component.getPublicInstance(); + warning( + instance !== null, + 'Stateless function components cannot have refs.' + ); + ref(instance); } else { // Legacy ref ReactOwner.addComponentAsRefTo( diff --git a/src/renderers/shared/stack/reconciler/__tests__/ReactStatelessComponent-test.js b/src/renderers/shared/stack/reconciler/__tests__/ReactStatelessComponent-test.js index 59d1e117ed6ae..7139c085aeb53 100644 --- a/src/renderers/shared/stack/reconciler/__tests__/ReactStatelessComponent-test.js +++ b/src/renderers/shared/stack/reconciler/__tests__/ReactStatelessComponent-test.js @@ -149,9 +149,9 @@ describe('ReactStatelessComponent', () => { it('should warn for functional refs in pure functions', function() { spyOn(console, 'error'); function Child() { - return
{}} />; + return
; } - ReactTestUtils.renderIntoDocument(); + ReactTestUtils.renderIntoDocument( {}} />); expect(console.error.calls.count()).toBe(1); expect(console.error.calls.argsFor(0)[0]).toContain( 'Stateless function components cannot have refs.' From 75f9efe90f0133101797a94105bc7c8eb436234a Mon Sep 17 00:00:00 2001 From: Brandon Dail Date: Wed, 13 Jul 2016 11:11:38 -0500 Subject: [PATCH 3/3] Add component/owner name to warning --- .../shared/stack/reconciler/ReactRef.js | 14 ++++++++++---- .../__tests__/ReactStatelessComponent-test.js | 16 +++++++++++----- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/renderers/shared/stack/reconciler/ReactRef.js b/src/renderers/shared/stack/reconciler/ReactRef.js index 64cfd15af6894..e5a0928671fc5 100644 --- a/src/renderers/shared/stack/reconciler/ReactRef.js +++ b/src/renderers/shared/stack/reconciler/ReactRef.js @@ -23,10 +23,16 @@ var ReactRef = {}; function attachRef(ref, component, owner) { if (typeof ref === 'function') { var instance = component.getPublicInstance(); - warning( - instance !== null, - 'Stateless function components cannot have refs.' - ); + if (__DEV__) { + var componentName = component && component.getName ? + component.getName() : 'a component'; + warning(instance != null, + 'Stateless function components cannot be given refs ' + + '(See %s%s).', + componentName, + owner ? ' created by ' + owner.getName() : '' + ); + } ref(instance); } else { // Legacy ref diff --git a/src/renderers/shared/stack/reconciler/__tests__/ReactStatelessComponent-test.js b/src/renderers/shared/stack/reconciler/__tests__/ReactStatelessComponent-test.js index 7139c085aeb53..0c7a6e1278eae 100644 --- a/src/renderers/shared/stack/reconciler/__tests__/ReactStatelessComponent-test.js +++ b/src/renderers/shared/stack/reconciler/__tests__/ReactStatelessComponent-test.js @@ -148,13 +148,19 @@ describe('ReactStatelessComponent', () => { it('should warn for functional refs in pure functions', function() { spyOn(console, 'error'); - function Child() { - return
; - } - ReactTestUtils.renderIntoDocument( {}} />); + + var Parent = React.createClass({ + displayName: 'Parent', + render: function() { + return {}}/>; + }, + }); + + ReactTestUtils.renderIntoDocument(); expect(console.error.calls.count()).toBe(1); expect(console.error.calls.argsFor(0)[0]).toContain( - 'Stateless function components cannot have refs.' + 'Stateless function components cannot be given refs ' + + '(See StatelessComponent created by Parent).', ); });