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 = {