Add monitor module for logging instrumentation

This adds an instrumentation hook for logging so that we can monitor invalid API
usage before we're ready to issue a warning.

I took the opportunity to update some console.warns to use the warning module
instead. The remaining console.warns
will be replaced by the warning module after we've cleaned up the callsites.
This commit is contained in:
Sebastian Markbage
2014-03-03 15:05:53 -08:00
committed by Paul O’Shannessy
parent f734083a17
commit eee04b19e1
8 changed files with 65 additions and 49 deletions
+5 -5
View File
@@ -23,6 +23,7 @@ var DOMProperty = require('DOMProperty');
var escapeTextForBrowser = require('escapeTextForBrowser');
var memoizeStringOnly = require('memoizeStringOnly');
var warning = require('warning');
function shouldIgnoreValue(name, value) {
return value == null ||
@@ -57,11 +58,10 @@ if (__DEV__) {
// For now, only warn when we have a suggested correction. This prevents
// logging too much when using transferPropsTo.
if (standardName != null) {
console.warn(
'Unknown DOM property ' + name + '. Did you mean ' + standardName + '?'
);
}
warning(
standardName == null,
'Unknown DOM property ' + name + '. Did you mean ' + standardName + '?'
);
};
}
+22 -23
View File
@@ -22,6 +22,7 @@
var ReactPropTypes = require('ReactPropTypes');
var invariant = require('invariant');
var warning = require('warning');
var hasReadOnlyValue = {
'button': true,
@@ -84,33 +85,31 @@ var LinkedValueUtils = {
propTypes: {
value: function(props, propName, componentName) {
if (__DEV__) {
if (props[propName] &&
!hasReadOnlyValue[props.type] &&
!props.onChange &&
!props.readOnly &&
!props.disabled) {
console.warn(
'You provided a `value` prop to a form field without an ' +
'`onChange` handler. This will render a read-only field. If ' +
'the field should be mutable use `defaultValue`. Otherwise, ' +
'set either `onChange` or `readOnly`.'
);
}
warning(
!props[propName] ||
hasReadOnlyValue[props.type] ||
props.onChange ||
props.readOnly ||
props.disabled,
'You provided a `value` prop to a form field without an ' +
'`onChange` handler. This will render a read-only field. If ' +
'the field should be mutable use `defaultValue`. Otherwise, ' +
'set either `onChange` or `readOnly`.'
);
}
},
checked: function(props, propName, componentName) {
if (__DEV__) {
if (props[propName] &&
!props.onChange &&
!props.readOnly &&
!props.disabled) {
console.warn(
'You provided a `checked` prop to a form field without an ' +
'`onChange` handler. This will render a read-only field. If ' +
'the field should be mutable use `defaultChecked`. Otherwise, ' +
'set either `onChange` or `readOnly`.'
);
}
warning(
!props[propName] ||
props.onChange ||
props.readOnly ||
props.disabled,
'You provided a `checked` prop to a form field without an ' +
'`onChange` handler. This will render a read-only field. If ' +
'the field should be mutable use `defaultChecked`. Otherwise, ' +
'set either `onChange` or `readOnly`.'
);
}
},
onChange: ReactPropTypes.func
+8 -7
View File
@@ -22,6 +22,8 @@ var ReactBrowserComponentMixin = require('ReactBrowserComponentMixin');
var ReactCompositeComponent = require('ReactCompositeComponent');
var ReactDOM = require('ReactDOM');
var warning = require('warning');
// Store a reference to the <option> `ReactDOMComponent`.
var option = ReactDOM.option;
@@ -35,13 +37,12 @@ var ReactDOMOption = ReactCompositeComponent.createClass({
componentWillMount: function() {
// TODO (yungsters): Remove support for `selected` in <option>.
if (this.props.selected != null) {
if (__DEV__) {
console.warn(
'Use the `defaultValue` or `value` props on <select> instead of ' +
'setting `selected` on <option>.'
);
}
if (__DEV__) {
warning(
this.props.selected == null,
'Use the `defaultValue` or `value` props on <select> instead of ' +
'setting `selected` on <option>.'
);
}
},
@@ -28,6 +28,8 @@ var ReactDOM = require('ReactDOM');
var invariant = require('invariant');
var merge = require('merge');
var warning = require('warning');
// Store a reference to the <textarea> `ReactDOMComponent`.
var textarea = ReactDOM.textarea;
@@ -57,7 +59,8 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({
var children = this.props.children;
if (children != null) {
if (__DEV__) {
console.warn(
warning(
false,
'Use the `defaultValue` or `value` props instead of setting ' +
'children on <textarea>.'
);
+3
View File
@@ -25,6 +25,7 @@ var ReactUpdates = require('ReactUpdates');
var invariant = require('invariant');
var keyMirror = require('keyMirror');
var merge = require('merge');
var monitorCodeUse = require('monitorCodeUse');
/**
* Every React component is in one of these life cycles.
@@ -116,6 +117,7 @@ function validateExplicitKey(component) {
}
message += ' See http://fb.me/react-warning-keys for more information.';
monitorCodeUse('react_key_warning');
console.warn(message);
}
@@ -136,6 +138,7 @@ function validatePropertyKey(name) {
}
ownerHasPropertyWarning[currentName] = true;
monitorCodeUse('react_numeric_key_warning');
console.warn(
'Child objects should have non-numeric keys so ordering is preserved. ' +
'Check the render method of ' + currentName + '. ' +
+14 -6
View File
@@ -33,8 +33,10 @@ var invariant = require('invariant');
var keyMirror = require('keyMirror');
var merge = require('merge');
var mixInto = require('mixInto');
var monitorCodeUse = require('monitorCodeUse');
var objMap = require('objMap');
var shouldUpdateReactComponent = require('shouldUpdateReactComponent');
var warning = require('warning');
/**
* Policies that describe methods in `ReactCompositeComponentInterface`.
@@ -621,6 +623,7 @@ if (__DEV__) {
var context = owner ? ' in ' + ownerName + '.' : ' at the top level.';
var staticMethodExample = '<' + name + ' />.type.' + key + '(...)';
monitorCodeUse('react_descriptor_property_access', { component: name });
console.warn(
'Invalid access to component property "' + key + '" on ' + name +
context + ' See http://fb.me/react-warning-descriptors .' +
@@ -904,12 +907,11 @@ var ReactCompositeComponentMixin = {
'setState(...): takes an object of state variables to update.'
);
if (__DEV__){
if (partialState == null) {
console.warn(
'setState(...): You passed an undefined or null state object; ' +
'instead, use forceUpdate().'
);
}
warning(
partialState != null,
'setState(...): You passed an undefined or null state object; ' +
'instead, use forceUpdate().'
);
}
// Merge with `_pendingState` if it exists, otherwise with existing state.
this.replaceState(
@@ -1332,11 +1334,13 @@ var ReactCompositeComponentMixin = {
// ignore the value of "this" that the user is trying to use, so
// let's warn.
if (newThis !== component && newThis !== null) {
monitorCodeUse('react_bind_warning', { component: componentName });
console.warn(
'bind(): React component methods may only be bound to the ' +
'component instance. See ' + componentName
);
} else if (!args.length) {
monitorCodeUse('react_bind_warning', { component: componentName });
console.warn(
'bind(): You are binding a component method to the component. ' +
'React does this for you automatically in a high-performance ' +
@@ -1421,6 +1425,10 @@ var ReactCompositeComponent = {
if (__DEV__) {
if (Constructor.prototype.componentShouldUpdate) {
monitorCodeUse(
'react_component_should_update_warning',
{ component: spec.displayName }
);
console.warn(
(spec.displayName || 'A component') + ' has a method called ' +
'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
+2
View File
@@ -26,6 +26,7 @@ var accumulate = require('accumulate');
var forEachAccumulated = require('forEachAccumulated');
var invariant = require('invariant');
var isEventSupported = require('isEventSupported');
var monitorCodeUse = require('monitorCodeUse');
/**
* Internal store for event listeners
@@ -168,6 +169,7 @@ var EventPluginHub = {
// bubble.
if (registrationName === 'onScroll' &&
!isEventSupported('scroll', true)) {
monitorCodeUse('react_no_scroll_event');
console.warn('This browser doesn\'t support the `onScroll` event');
}
}
+7 -7
View File
@@ -22,6 +22,7 @@
var ReactPropTransferer = require('ReactPropTransferer');
var keyOf = require('keyOf');
var warning = require('warning');
var CHILDREN_PROP = keyOf({children: null});
@@ -36,13 +37,12 @@ var CHILDREN_PROP = keyOf({children: null});
*/
function cloneWithProps(child, props) {
if (__DEV__) {
if (child.props.ref) {
console.warn(
'You are calling cloneWithProps() on a child with a ref. This is ' +
'dangerous because you\'re creating a new child which will not be ' +
'added as a ref to its parent.'
);
}
warning(
!child.props.ref,
'You are calling cloneWithProps() on a child with a ref. This is ' +
'dangerous because you\'re creating a new child which will not be ' +
'added as a ref to its parent.'
);
}
var newProps = ReactPropTransferer.mergeProps(props, child.props);