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