From 39265cb89266a90dcab4830133979038aeffd8e3 Mon Sep 17 00:00:00 2001 From: Griffin Michl Date: Thu, 30 Jun 2016 16:13:32 -0700 Subject: [PATCH] Group warnings for unknown DOM properties (#7153) --- .../__tests__/ReactDOMComponent-test.js | 11 ++++ .../ReactDOMUnknownPropertyDevtool.js | 58 ++++++++++++++----- 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js b/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js index 39d849008c..bcc843c1b7 100644 --- a/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js +++ b/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js @@ -163,6 +163,17 @@ describe('ReactDOMComponent', function() { ); }); + it('should group multiple unknown prop warnings together', function() { + spyOn(console, 'error'); + var container = document.createElement('div'); + ReactDOM.render(
, container); + expect(console.error.calls.count(0)).toBe(1); + expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe( + 'Warning: Unknown props `foo`, `baz` on
tag. Remove these props from the element. ' + + 'For details, see https://fb.me/react-unknown-prop\n in div (at **)' + ); + }); + it('should warn for onDblClick prop', function() { spyOn(console, 'error'); var container = document.createElement('div'); diff --git a/src/renderers/dom/shared/devtools/ReactDOMUnknownPropertyDevtool.js b/src/renderers/dom/shared/devtools/ReactDOMUnknownPropertyDevtool.js index 8d25523efa..e37be4a257 100644 --- a/src/renderers/dom/shared/devtools/ReactDOMUnknownPropertyDevtool.js +++ b/src/renderers/dom/shared/devtools/ReactDOMUnknownPropertyDevtool.js @@ -36,16 +36,16 @@ if (__DEV__) { }; var warnedProperties = {}; - var warnUnknownProperty = function(tagName, name, debugID) { + var validateProperty = function(tagName, name, debugID) { if (DOMProperty.properties.hasOwnProperty(name) || DOMProperty.isCustomAttribute(name)) { - return; + return true; } if (reactProps.hasOwnProperty(name) && reactProps[name] || warnedProperties.hasOwnProperty(name) && warnedProperties[name]) { - return; + return true; } if (EventPluginRegistry.registrationNameModules.hasOwnProperty(name)) { - return; + return true; } warnedProperties[name] = true; var lowerCasedName = name.toLowerCase(); @@ -75,6 +75,7 @@ if (__DEV__) { standardName, ReactComponentTreeDevtool.getStackAddendumByID(debugID) ); + return true; } else if (registrationName != null) { warning( registrationName == null, @@ -83,22 +84,51 @@ if (__DEV__) { registrationName, ReactComponentTreeDevtool.getStackAddendumByID(debugID) ); + return true; } else { // We were unable to guess which prop the user intended. // It is likely that the user was just blindly spreading/forwarding props // Components should be careful to only render valid props/attributes. - warning( - false, - 'Unknown prop `%s` on <%s> tag. Remove this prop from the element. ' + - 'For details, see https://fb.me/react-unknown-prop%s', - name, - tagName, - ReactComponentTreeDevtool.getStackAddendumByID(debugID) - ); + // Warning will be invoked in warnUnknownProperties to allow grouping. + return false; } }; } +var warnUnknownProperties = function(debugID, element) { + var unknownProps = []; + for (var key in element.props) { + var isValid = validateProperty(element.type, key, debugID); + if (!isValid) { + unknownProps.push(key); + } + } + + var unknownPropString = unknownProps + .map(prop => '`' + prop + '`') + .join(', '); + + if (unknownProps.length === 1) { + warning( + false, + 'Unknown prop %s on <%s> tag. Remove this prop from the element. ' + + 'For details, see https://fb.me/react-unknown-prop%s', + unknownPropString, + element.type, + ReactComponentTreeDevtool.getStackAddendumByID(debugID) + ); + } else if (unknownProps.length > 1) { + warning( + false, + 'Unknown props %s on <%s> tag. Remove these props from the element. ' + + 'For details, see https://fb.me/react-unknown-prop%s', + unknownPropString, + element.type, + ReactComponentTreeDevtool.getStackAddendumByID(debugID) + ); + } +}; + function handleElement(debugID, element) { if (element == null || typeof element.type !== 'string') { return; @@ -106,9 +136,7 @@ function handleElement(debugID, element) { if (element.type.indexOf('-') >= 0 || element.props.is) { return; } - for (var key in element.props) { - warnUnknownProperty(element.type, key, debugID); - } + warnUnknownProperties(debugID, element); } var ReactDOMUnknownPropertyDevtool = {