mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Merge pull request #267 from spicyj/warn-props
Warn about unknown property values
This commit is contained in:
@@ -102,7 +102,12 @@ var ReactTransitionGroup = React.createClass({
|
||||
render: function() {
|
||||
return this.transferPropsTo(
|
||||
this.props.component(
|
||||
null,
|
||||
{
|
||||
transitionName: null,
|
||||
transitionEnter: null,
|
||||
transitionLeave: null,
|
||||
component: null
|
||||
},
|
||||
this.renderTransitionableChildren(this.props.children)
|
||||
)
|
||||
);
|
||||
|
||||
+11
-1
@@ -82,8 +82,11 @@ var DOMPropertyInjection = {
|
||||
|
||||
DOMProperty.isStandardName[propName] = true;
|
||||
|
||||
var lowerCased = propName.toLowerCase();
|
||||
DOMProperty.getPossibleStandardName[lowerCased] = propName;
|
||||
|
||||
DOMProperty.getAttributeName[propName] =
|
||||
DOMAttributeNames[propName] || propName.toLowerCase();
|
||||
DOMAttributeNames[propName] || lowerCased;
|
||||
|
||||
DOMProperty.getPropertyName[propName] =
|
||||
DOMPropertyNames[propName] || propName;
|
||||
@@ -141,6 +144,13 @@ var DOMProperty = {
|
||||
*/
|
||||
isStandardName: {},
|
||||
|
||||
/**
|
||||
* Mapping from lowercase property names to the properly cased version, used
|
||||
* to warn in the case of missing properties.
|
||||
* @type {Object}
|
||||
*/
|
||||
getPossibleStandardName: {},
|
||||
|
||||
/**
|
||||
* Mapping from normalized names to attribute names that differ. Attribute
|
||||
* names are used when rendering markup or with `*Attribute()`.
|
||||
|
||||
@@ -28,6 +28,36 @@ var processAttributeNameAndPrefix = memoizeStringOnly(function(name) {
|
||||
return escapeTextForBrowser(name) + '="';
|
||||
});
|
||||
|
||||
if (__DEV__) {
|
||||
var reactProps = {
|
||||
'{owner}': true,
|
||||
children: true,
|
||||
dangerouslySetInnerHTML: true,
|
||||
key: true,
|
||||
ref: true
|
||||
};
|
||||
var warnedProperties = {};
|
||||
|
||||
var warnUnknownProperty = function(name) {
|
||||
if (reactProps[name] || warnedProperties[name]) {
|
||||
return;
|
||||
}
|
||||
|
||||
warnedProperties[name] = true;
|
||||
var message = 'Unknown DOM property ' + name + '.';
|
||||
var lowerCasedName = name.toLowerCase();
|
||||
|
||||
// data-* attributes should be lowercase; suggest the lowercase version
|
||||
var standardName = DOMProperty.isCustomAttribute(lowerCasedName) ?
|
||||
lowerCasedName : DOMProperty.getPossibleStandardName[lowerCasedName];
|
||||
if (standardName != null) {
|
||||
message += ' Did you mean ' + standardName + '?';
|
||||
}
|
||||
|
||||
console.warn(message);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Operations for dealing with DOM properties.
|
||||
*/
|
||||
@@ -55,6 +85,9 @@ var DOMPropertyOperations = {
|
||||
return processAttributeNameAndPrefix(name) +
|
||||
escapeTextForBrowser(value) + '"';
|
||||
} else {
|
||||
if (__DEV__) {
|
||||
warnUnknownProperty(name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
},
|
||||
@@ -85,6 +118,10 @@ var DOMPropertyOperations = {
|
||||
}
|
||||
} else if (DOMProperty.isCustomAttribute(name)) {
|
||||
node.setAttribute(name, value);
|
||||
} else {
|
||||
if (__DEV__) {
|
||||
warnUnknownProperty(name);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -110,6 +147,8 @@ var DOMPropertyOperations = {
|
||||
}
|
||||
} else if (DOMProperty.isCustomAttribute(name)) {
|
||||
node.removeAttribute(name);
|
||||
} else if (__DEV__) {
|
||||
warnUnknownProperty(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,16 @@ describe('DOMPropertyOperations', function() {
|
||||
)).toBe('id="simple"');
|
||||
});
|
||||
|
||||
it('should warn about incorrect casing', function() {
|
||||
spyOn(console, 'warn');
|
||||
expect(DOMPropertyOperations.createMarkupForProperty(
|
||||
'tabindex',
|
||||
'1'
|
||||
)).toBe(null);
|
||||
expect(console.warn.argsForCall.length).toBe(1);
|
||||
expect(console.warn.argsForCall[0][0]).toContain('tabIndex');
|
||||
});
|
||||
|
||||
it('should create markup for boolean properties', function() {
|
||||
expect(DOMPropertyOperations.createMarkupForProperty(
|
||||
'checked',
|
||||
@@ -141,18 +151,24 @@ describe('DOMPropertyOperations', function() {
|
||||
|
||||
describe('injectDOMPropertyConfig', function() {
|
||||
it('should support custom attributes', function() {
|
||||
spyOn(console, 'warn');
|
||||
|
||||
// foobar does not exist yet
|
||||
expect(DOMPropertyOperations.createMarkupForProperty(
|
||||
'foobar',
|
||||
'simple'
|
||||
)).toBe(null);
|
||||
|
||||
expect(console.warn.argsForCall.length).toBe(1);
|
||||
|
||||
// foo-* does not exist yet
|
||||
expect(DOMPropertyOperations.createMarkupForProperty(
|
||||
'foo-xyz',
|
||||
'simple'
|
||||
)).toBe(null);
|
||||
|
||||
expect(console.warn.argsForCall.length).toBe(2);
|
||||
|
||||
// inject foobar DOM property
|
||||
DOMProperty.injection.injectDOMPropertyConfig({
|
||||
isCustomAttribute: function(name) {
|
||||
|
||||
@@ -61,6 +61,8 @@ var ReactDOMInput = ReactCompositeComponent.createClass({
|
||||
// Clone `this.props` so we don't mutate the input.
|
||||
var props = merge(this.props);
|
||||
|
||||
props.defaultChecked = null;
|
||||
props.defaultValue = null;
|
||||
props.checked =
|
||||
this.props.checked != null ? this.props.checked : this.state.checked;
|
||||
// Cast `this.props.value` to a string so equality checks pass.
|
||||
|
||||
@@ -102,6 +102,7 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({
|
||||
'`dangerouslySetInnerHTML` does not make sense on <textarea>.'
|
||||
);
|
||||
|
||||
props.defaultValue = null;
|
||||
props.value =
|
||||
this.props.value != null ? this.props.value : this.state.value;
|
||||
props.onChange = this._handleChange;
|
||||
|
||||
Reference in New Issue
Block a user