@samitouri / QOS-React / commits / 2e881aa4b4

Fire unknown prop warning when rendering client side. (#6693)

Jim committed May 17, 2016 at 15:06 UTC 2e881aa4b432261e4ce8aba52d06cc616c8330f0
2 files changed +39 -25
src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js
+18 -2
@@ -1275,14 +1275,14 @@ describe('ReactDOMComponent', function() {
1275 );
1276 });
1277
1278 - it('should warn about incorrect casing on properties', function() {
1278 + it('should warn about incorrect casing on properties (ssr)', function() {
1279 spyOn(console, 'error');
1280 ReactDOMServer.renderToString(React.createElement('input', {type: 'text', tabindex: '1'}));
1281 expect(console.error.argsForCall.length).toBe(1);
1282 expect(console.error.argsForCall[0][0]).toContain('tabIndex');
1283 });
1284
1285 - it('should warn about incorrect casing on event handlers', function() {
1285 + it('should warn about incorrect casing on event handlers (ssr)', function() {
1286 spyOn(console, 'error');
1287 ReactDOMServer.renderToString(React.createElement('input', {type: 'text', onclick: '1'}));
1288 ReactDOMServer.renderToString(React.createElement('input', {type: 'text', onKeydown: '1'}));
@@ -1291,6 +1291,22 @@ describe('ReactDOMComponent', function() {
1291 expect(console.error.argsForCall[1][0]).toContain('onKeyDown');
1292 });
1293
1294 + it('should warn about incorrect casing on properties', function() {
1295 + spyOn(console, 'error');
1296 + ReactTestUtils.renderIntoDocument(React.createElement('input', {type: 'text', tabindex: '1'}));
1297 + expect(console.error.argsForCall.length).toBe(1);
1298 + expect(console.error.argsForCall[0][0]).toContain('tabIndex');
1299 + });
1300 +
1301 + it('should warn about incorrect casing on event handlers', function() {
1302 + spyOn(console, 'error');
1303 + ReactTestUtils.renderIntoDocument(React.createElement('input', {type: 'text', onclick: '1'}));
1304 + ReactTestUtils.renderIntoDocument(React.createElement('input', {type: 'text', onKeydown: '1'}));
1305 + expect(console.error.argsForCall.length).toBe(2);
1306 + expect(console.error.argsForCall[0][0]).toContain('onClick');
1307 + expect(console.error.argsForCall[1][0]).toContain('onKeyDown');
1308 + });
1309 +
1310 it('should warn about class', function() {
1311 spyOn(console, 'error');
1312 ReactDOMServer.renderToString(React.createElement('div', {class: 'muffins'}));
src/renderers/dom/shared/devtools/ReactDOMUnknownPropertyDevtool.js
+21 -23
@@ -13,12 +13,10 @@
13
14 var DOMProperty = require('DOMProperty');
15 var EventPluginRegistry = require('EventPluginRegistry');
16 -var ReactComponentTreeDevtool = require('ReactComponentTreeDevtool');
16
17 var warning = require('warning');
18
19 if (__DEV__) {
21 - var lastDebugID;
20 var reactProps = {
21 children: true,
22 dangerouslySetInnerHTML: true,
@@ -27,7 +25,7 @@ if (__DEV__) {
25 };
26 var warnedProperties = {};
27
30 - var warnUnknownProperty = function(name) {
28 + var warnUnknownProperty = function(name, source) {
29 if (DOMProperty.properties.hasOwnProperty(name) || DOMProperty.isCustomAttribute(name)) {
30 return;
31 }
@@ -35,7 +33,9 @@ if (__DEV__) {
33 warnedProperties.hasOwnProperty(name) && warnedProperties[name]) {
34 return;
35 }
38 -
36 + if (EventPluginRegistry.registrationNameModules.hasOwnProperty(name)) {
37 + return;
38 + }
39 warnedProperties[name] = true;
40 var lowerCasedName = name.toLowerCase();
41
@@ -48,10 +48,6 @@ if (__DEV__) {
48 null
49 );
50
51 - var source = ReactComponentTreeDevtool.getSource(lastDebugID);
52 - var formattedSource = source ?
53 - `(${source.fileName.replace(/^.*[\\\/]/, '')}:${source.lineNumber})` : '';
54 -
51 // For now, only warn when we have a suggested correction. This prevents
52 // logging too much when using transferPropsTo.
53 warning(
@@ -59,7 +55,7 @@ if (__DEV__) {
55 'Unknown DOM property %s. Did you mean %s? %s',
56 name,
57 standardName,
62 - formattedSource
58 + formatSource(source)
59 );
60
61 var registrationName = (
@@ -75,29 +71,31 @@ if (__DEV__) {
71 'Unknown event handler property %s. Did you mean `%s`? %s',
72 name,
73 registrationName,
78 - formattedSource
74 + formatSource(source)
75 );
76 };
77
78 + var formatSource = function(source) {
79 + return source ? `(${source.fileName.replace(/^.*[\\\/]/, '')}:${source.lineNumber})` : '';
80 + };
81 +
82 +}
83 +
84 +function handleElement(element) {
85 + if (element == null || typeof element.type !== 'string') {
86 + return;
87 + }
88 + for (var key in element.props) {
89 + warnUnknownProperty(key, element._source);
90 + }
91 }
92
93 var ReactDOMUnknownPropertyDevtool = {
85 - onCreateMarkupForProperty(name, value) {
86 - warnUnknownProperty(name);
87 - },
88 - onSetValueForProperty(node, name, value) {
89 - warnUnknownProperty(name);
90 - },
91 - onDeleteValueForProperty(node, name) {
92 - warnUnknownProperty(name);
93 - },
94 onBeforeMountComponent(debugID, element) {
95 - // TODO: This currently assumes that properties are all set before recursing
96 - // and mounting children, which needn't be the case in the future.
97 - lastDebugID = debugID;
95 + handleElement(element);
96 },
97 onBeforeUpdateComponent(debugID, element) {
100 - lastDebugID = debugID;
98 + handleElement(element);
99 },
100 };
101