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.
Sebastian Markbage committed
Mar 3, 2014 at 09:39 UTC
eee04b19e1866fdf5fb40298dbbfe7804b691d26
8 files changed
+65
-49
src/browser/dom/DOMPropertyOperations.js
+5
-5
@@ -23,6 +23,7 @@ var DOMProperty = require('DOMProperty');
23
24
var escapeTextForBrowser = require('escapeTextForBrowser');
25
var memoizeStringOnly = require('memoizeStringOnly');
26
+var warning = require('warning');
27
28
function shouldIgnoreValue(name, value) {
29
return value == null ||
@@ -57,11 +58,10 @@ if (__DEV__) {
58
59
// For now, only warn when we have a suggested correction. This prevents
60
// logging too much when using transferPropsTo.
60
- if (standardName != null) {
61
- console.warn(
62
- 'Unknown DOM property ' + name + '. Did you mean ' + standardName + '?'
63
- );
64
- }
61
+ warning(
62
+ standardName == null,
63
+ 'Unknown DOM property ' + name + '. Did you mean ' + standardName + '?'
64
+ );
65
66
};
67
}
src/browser/dom/components/LinkedValueUtils.js
+22
-23
@@ -22,6 +22,7 @@
22
var ReactPropTypes = require('ReactPropTypes');
23
24
var invariant = require('invariant');
25
+var warning = require('warning');
26
27
var hasReadOnlyValue = {
28
'button': true,
@@ -84,33 +85,31 @@ var LinkedValueUtils = {
85
propTypes: {
86
value: function(props, propName, componentName) {
87
if (__DEV__) {
87
- if (props[propName] &&
88
- !hasReadOnlyValue[props.type] &&
89
- !props.onChange &&
90
- !props.readOnly &&
91
- !props.disabled) {
92
- console.warn(
93
- 'You provided a `value` prop to a form field without an ' +
94
- '`onChange` handler. This will render a read-only field. If ' +
95
- 'the field should be mutable use `defaultValue`. Otherwise, ' +
96
- 'set either `onChange` or `readOnly`.'
97
- );
98
- }
88
+ warning(
89
+ !props[propName] ||
90
+ hasReadOnlyValue[props.type] ||
91
+ props.onChange ||
92
+ props.readOnly ||
93
+ props.disabled,
94
+ 'You provided a `value` prop to a form field without an ' +
95
+ '`onChange` handler. This will render a read-only field. If ' +
96
+ 'the field should be mutable use `defaultValue`. Otherwise, ' +
97
+ 'set either `onChange` or `readOnly`.'
98
+ );
99
}
100
},
101
checked: function(props, propName, componentName) {
102
if (__DEV__) {
103
- if (props[propName] &&
104
- !props.onChange &&
105
- !props.readOnly &&
106
- !props.disabled) {
107
- console.warn(
108
- 'You provided a `checked` prop to a form field without an ' +
109
- '`onChange` handler. This will render a read-only field. If ' +
110
- 'the field should be mutable use `defaultChecked`. Otherwise, ' +
111
- 'set either `onChange` or `readOnly`.'
112
- );
113
- }
103
+ warning(
104
+ !props[propName] ||
105
+ props.onChange ||
106
+ props.readOnly ||
107
+ props.disabled,
108
+ 'You provided a `checked` prop to a form field without an ' +
109
+ '`onChange` handler. This will render a read-only field. If ' +
110
+ 'the field should be mutable use `defaultChecked`. Otherwise, ' +
111
+ 'set either `onChange` or `readOnly`.'
112
+ );
113
}
114
},
115
onChange: ReactPropTypes.func
src/browser/dom/components/ReactDOMOption.js
+8
-7
@@ -22,6 +22,8 @@ var ReactBrowserComponentMixin = require('ReactBrowserComponentMixin');
22
var ReactCompositeComponent = require('ReactCompositeComponent');
23
var ReactDOM = require('ReactDOM');
24
25
+var warning = require('warning');
26
+
27
// Store a reference to the <option> `ReactDOMComponent`.
28
var option = ReactDOM.option;
29
@@ -35,13 +37,12 @@ var ReactDOMOption = ReactCompositeComponent.createClass({
37
38
componentWillMount: function() {
39
// TODO (yungsters): Remove support for `selected` in <option>.
38
- if (this.props.selected != null) {
39
- if (__DEV__) {
40
- console.warn(
41
- 'Use the `defaultValue` or `value` props on <select> instead of ' +
42
- 'setting `selected` on <option>.'
43
- );
44
- }
40
+ if (__DEV__) {
41
+ warning(
42
+ this.props.selected == null,
43
+ 'Use the `defaultValue` or `value` props on <select> instead of ' +
44
+ 'setting `selected` on <option>.'
45
+ );
46
}
47
},
48
src/browser/dom/components/ReactDOMTextarea.js
+4
-1
@@ -28,6 +28,8 @@ var ReactDOM = require('ReactDOM');
28
var invariant = require('invariant');
29
var merge = require('merge');
30
31
+var warning = require('warning');
32
+
33
// Store a reference to the <textarea> `ReactDOMComponent`.
34
var textarea = ReactDOM.textarea;
35
@@ -57,7 +59,8 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({
59
var children = this.props.children;
60
if (children != null) {
61
if (__DEV__) {
60
- console.warn(
62
+ warning(
63
+ false,
64
'Use the `defaultValue` or `value` props instead of setting ' +
65
'children on <textarea>.'
66
);
src/core/ReactComponent.js
+3
@@ -25,6 +25,7 @@ var ReactUpdates = require('ReactUpdates');
25
var invariant = require('invariant');
26
var keyMirror = require('keyMirror');
27
var merge = require('merge');
28
+var monitorCodeUse = require('monitorCodeUse');
29
30
/**
31
* Every React component is in one of these life cycles.
@@ -116,6 +117,7 @@ function validateExplicitKey(component) {
117
}
118
119
message += ' See http://fb.me/react-warning-keys for more information.';
120
+ monitorCodeUse('react_key_warning');
121
console.warn(message);
122
}
123
@@ -136,6 +138,7 @@ function validatePropertyKey(name) {
138
}
139
ownerHasPropertyWarning[currentName] = true;
140
141
+ monitorCodeUse('react_numeric_key_warning');
142
console.warn(
143
'Child objects should have non-numeric keys so ordering is preserved. ' +
144
'Check the render method of ' + currentName + '. ' +
src/core/ReactCompositeComponent.js
+14
-6
@@ -33,8 +33,10 @@ var invariant = require('invariant');
33
var keyMirror = require('keyMirror');
34
var merge = require('merge');
35
var mixInto = require('mixInto');
36
+var monitorCodeUse = require('monitorCodeUse');
37
var objMap = require('objMap');
38
var shouldUpdateReactComponent = require('shouldUpdateReactComponent');
39
+var warning = require('warning');
40
41
/**
42
* Policies that describe methods in `ReactCompositeComponentInterface`.
@@ -621,6 +623,7 @@ if (__DEV__) {
623
var context = owner ? ' in ' + ownerName + '.' : ' at the top level.';
624
var staticMethodExample = '<' + name + ' />.type.' + key + '(...)';
625
626
+ monitorCodeUse('react_descriptor_property_access', { component: name });
627
console.warn(
628
'Invalid access to component property "' + key + '" on ' + name +
629
context + ' See http://fb.me/react-warning-descriptors .' +
@@ -904,12 +907,11 @@ var ReactCompositeComponentMixin = {
907
'setState(...): takes an object of state variables to update.'
908
);
909
if (__DEV__){
907
- if (partialState == null) {
908
- console.warn(
909
- 'setState(...): You passed an undefined or null state object; ' +
910
- 'instead, use forceUpdate().'
911
- );
912
- }
910
+ warning(
911
+ partialState != null,
912
+ 'setState(...): You passed an undefined or null state object; ' +
913
+ 'instead, use forceUpdate().'
914
+ );
915
}
916
// Merge with `_pendingState` if it exists, otherwise with existing state.
917
this.replaceState(
@@ -1332,11 +1334,13 @@ var ReactCompositeComponentMixin = {
1334
// ignore the value of "this" that the user is trying to use, so
1335
// let's warn.
1336
if (newThis !== component && newThis !== null) {
1337
+ monitorCodeUse('react_bind_warning', { component: componentName });
1338
console.warn(
1339
'bind(): React component methods may only be bound to the ' +
1340
'component instance. See ' + componentName
1341
);
1342
} else if (!args.length) {
1343
+ monitorCodeUse('react_bind_warning', { component: componentName });
1344
console.warn(
1345
'bind(): You are binding a component method to the component. ' +
1346
'React does this for you automatically in a high-performance ' +
@@ -1421,6 +1425,10 @@ var ReactCompositeComponent = {
1425
1426
if (__DEV__) {
1427
if (Constructor.prototype.componentShouldUpdate) {
1428
+ monitorCodeUse(
1429
+ 'react_component_should_update_warning',
1430
+ { component: spec.displayName }
1431
+ );
1432
console.warn(
1433
(spec.displayName || 'A component') + ' has a method called ' +
1434
'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
src/event/EventPluginHub.js
+2
@@ -26,6 +26,7 @@ var accumulate = require('accumulate');
26
var forEachAccumulated = require('forEachAccumulated');
27
var invariant = require('invariant');
28
var isEventSupported = require('isEventSupported');
29
+var monitorCodeUse = require('monitorCodeUse');
30
31
/**
32
* Internal store for event listeners
@@ -168,6 +169,7 @@ var EventPluginHub = {
169
// bubble.
170
if (registrationName === 'onScroll' &&
171
!isEventSupported('scroll', true)) {
172
+ monitorCodeUse('react_no_scroll_event');
173
console.warn('This browser doesn\'t support the `onScroll` event');
174
}
175
}
src/utils/cloneWithProps.js
+7
-7
@@ -22,6 +22,7 @@
22
var ReactPropTransferer = require('ReactPropTransferer');
23
24
var keyOf = require('keyOf');
25
+var warning = require('warning');
26
27
var CHILDREN_PROP = keyOf({children: null});
28
@@ -36,13 +37,12 @@ var CHILDREN_PROP = keyOf({children: null});
37
*/
38
function cloneWithProps(child, props) {
39
if (__DEV__) {
39
- if (child.props.ref) {
40
- console.warn(
41
- 'You are calling cloneWithProps() on a child with a ref. This is ' +
42
- 'dangerous because you\'re creating a new child which will not be ' +
43
- 'added as a ref to its parent.'
44
- );
45
- }
40
+ warning(
41
+ !child.props.ref,
42
+ 'You are calling cloneWithProps() on a child with a ref. This is ' +
43
+ 'dangerous because you\'re creating a new child which will not be ' +
44
+ 'added as a ref to its parent.'
45
+ );
46
}
47
48
var newProps = ReactPropTransferer.mergeProps(props, child.props);