diff --git a/src/core/ReactCompositeComponent.js b/src/core/ReactCompositeComponent.js index 87a8de23b3f..69486ca1e37 100644 --- a/src/core/ReactCompositeComponent.js +++ b/src/core/ReactCompositeComponent.js @@ -987,7 +987,19 @@ var ReactCompositeComponentMixin = { // TODO: Stop validating prop types here and only use the descriptor // validation. var componentName = this.constructor.displayName; - for (var propName in propTypes) { + var propName; + + for (propName in props) { + if (props.hasOwnProperty(propName) && + !propTypes.hasOwnProperty(propName)) { + var message = location.substring(0,1).toUpperCase() + + location.substring(1) + " `" + propName + + "` was not expected in " + ("`" + componentName + "`."); + warning(false, message); + } + } + + for (propName in propTypes) { if (propTypes.hasOwnProperty(propName)) { var error = propTypes[propName](props, propName, componentName, location); diff --git a/src/core/ReactDescriptorValidator.js b/src/core/ReactDescriptorValidator.js index 4123160d170..1b2dce86017 100644 --- a/src/core/ReactDescriptorValidator.js +++ b/src/core/ReactDescriptorValidator.js @@ -199,7 +199,22 @@ function validateChildKeys(component, parentType) { * @private */ function checkPropTypes(componentName, propTypes, props, location) { - for (var propName in propTypes) { + var propName; + for (propName in props) { + if (props.hasOwnProperty(propName) && + !propTypes.hasOwnProperty(propName)) { + var message = location.substring(0,1).toUpperCase() + + location.substring(1) + " `" + propName + + "` was not expected in " + ("`" + componentName + "`."); + loggedTypeFailures[message] = true; + monitorCodeUse( + 'react_failed_descriptor_type_check', + { message: message } + ); + } + } + + for (propName in propTypes) { if (propTypes.hasOwnProperty(propName)) { var error; // Prop type validation may throw. In case they do, we don't want to diff --git a/src/core/__tests__/ReactCompositeComponent-test.js b/src/core/__tests__/ReactCompositeComponent-test.js index a970b171693..e3f1b77197c 100644 --- a/src/core/__tests__/ReactCompositeComponent-test.js +++ b/src/core/__tests__/ReactCompositeComponent-test.js @@ -553,6 +553,22 @@ describe('ReactCompositeComponent', function() { expect(console.warn.mock.calls.length).toBe(2); }); + it('should warn about unexpected props', function() { + var Component = React.createClass({ + propTypes: {}, + render: function() { + return {this.props.prop}; + } + }); + + ReactTestUtils.renderIntoDocument(); + + expect(console.warn.mock.calls.length).toBe(1); + expect(console.warn.mock.calls[0][0]).toBe( + 'Warning: Prop `prop` was not expected in `Component`.' + ); + }); + it('should throw on invalid prop types', function() { expect(function() { React.createClass({