From 26e0aa188eda43b9c1b10bef89baaf24ae9db73e Mon Sep 17 00:00:00 2001 From: Evan Scott Date: Mon, 10 Sep 2018 23:43:49 -0500 Subject: [PATCH 1/4] add failing test --- .../react/src/__tests__/forwardRef-test.js | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/packages/react/src/__tests__/forwardRef-test.js b/packages/react/src/__tests__/forwardRef-test.js index 277f87fd9fe8..82e096e57341 100644 --- a/packages/react/src/__tests__/forwardRef-test.js +++ b/packages/react/src/__tests__/forwardRef-test.js @@ -181,4 +181,33 @@ describe('forwardRef', () => { {withoutStack: true}, ); }); + + it('should honor a displayName if set on the forwardRef wrapper in warnings', () => { + const Component = props =>
; + + const RefForwardingComponent = React.forwardRef((props, ref) => ( + + )); + + RefForwardingComponent.displayName = 'Foo'; + + RefForwardingComponent.propTypes = { + optional: PropTypes.string, + required: PropTypes.string.isRequired, + }; + + RefForwardingComponent.defaultProps = { + optional: 'default', + }; + + const ref = React.createRef(); + + expect(() => + ReactNoop.render(), + ).toWarnDev( + 'Warning: Failed prop type: The prop `required` is marked as required in ' + + '`Foo`, but its value is `undefined`.\n' + + ' in Foo (at **)', + ); + }); }); From 807aee50d80921d1ae84365d73a1aedcc599808f Mon Sep 17 00:00:00 2001 From: Evan Scott Date: Mon, 10 Sep 2018 23:52:01 -0500 Subject: [PATCH 2/4] honor displayName set on ForwardRef if available Since React.forwardRef returns a component object, some users (including styled-components and react-native) are starting to decorate them with various statics including displayName. This adjusts React's various name-getters to honor this if set and surface the name in warnings and hopefully DevTools. --- packages/react/src/ReactElementValidator.js | 4 +++- packages/shared/getComponentName.js | 7 ++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/react/src/ReactElementValidator.js b/packages/react/src/ReactElementValidator.js index 8b03c3a92ae7..c38897ac139b 100644 --- a/packages/react/src/ReactElementValidator.js +++ b/packages/react/src/ReactElementValidator.js @@ -197,7 +197,9 @@ function validatePropTypes(element) { ) { // ForwardRef const functionName = type.render.displayName || type.render.name || ''; - name = functionName !== '' ? `ForwardRef(${functionName})` : 'ForwardRef'; + name = + type.displayName || + (functionName !== '' ? `ForwardRef(${functionName})` : 'ForwardRef'); propTypes = type.propTypes; } else { return; diff --git a/packages/shared/getComponentName.js b/packages/shared/getComponentName.js index 18793dc5feb3..a1b497ab0026 100644 --- a/packages/shared/getComponentName.js +++ b/packages/shared/getComponentName.js @@ -66,9 +66,10 @@ function getComponentName(type: mixed): string | null { case REACT_FORWARD_REF_TYPE: const renderFn = (type.render: any); const functionName = renderFn.displayName || renderFn.name || ''; - return functionName !== '' - ? `ForwardRef(${functionName})` - : 'ForwardRef'; + return ( + type.displayName || + (functionName !== '' ? `ForwardRef(${functionName})` : 'ForwardRef') + ); } if (typeof type.then === 'function') { const thenable: Thenable = (type: any); From 7b1b7b76a1ee7cb3e919898c3488e4228a13688c Mon Sep 17 00:00:00 2001 From: Evan Scott Date: Tue, 11 Sep 2018 00:17:07 -0500 Subject: [PATCH 3/4] fix typing --- packages/shared/getComponentName.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared/getComponentName.js b/packages/shared/getComponentName.js index a1b497ab0026..58e7ea47f8ea 100644 --- a/packages/shared/getComponentName.js +++ b/packages/shared/getComponentName.js @@ -23,7 +23,7 @@ import { } from 'shared/ReactSymbols'; import {refineResolvedThenable} from 'shared/ReactLazyComponent'; -function getComponentName(type: mixed): string | null { +function getComponentName(type: any): string | null { if (type == null) { // Host root, text node or just invalid type. return null; From fc03666429cd42e4432e3c0f8d15fc392598b4aa Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Tue, 11 Sep 2018 20:18:46 +0100 Subject: [PATCH 4/4] Refine later --- packages/shared/getComponentName.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/shared/getComponentName.js b/packages/shared/getComponentName.js index 58e7ea47f8ea..e39a6965e02e 100644 --- a/packages/shared/getComponentName.js +++ b/packages/shared/getComponentName.js @@ -23,7 +23,7 @@ import { } from 'shared/ReactSymbols'; import {refineResolvedThenable} from 'shared/ReactLazyComponent'; -function getComponentName(type: any): string | null { +function getComponentName(type: mixed): string | null { if (type == null) { // Host root, text node or just invalid type. return null; @@ -67,7 +67,7 @@ function getComponentName(type: any): string | null { const renderFn = (type.render: any); const functionName = renderFn.displayName || renderFn.name || ''; return ( - type.displayName || + (type: any).displayName || (functionName !== '' ? `ForwardRef(${functionName})` : 'ForwardRef') ); }