Moar warnings with solid prefixes!

This ensures that we have a prefix that can be easily identified in logs
so that we can filter out warnings based on their prefix.

This also turns the remaining two monitorCodeUse callers into warnings.
We'll probably still use monitorCodeUse until we know if we want to
deprecate but most releases should only have warnings.
This commit is contained in:
Sebastian Markbage 2015-02-12 13:37:19 -08:00
parent d2fcdfc7df
commit f5038829d8
7 changed files with 65 additions and 32 deletions

View File

@ -147,7 +147,8 @@ describe('ReactContextValidator', function() {
expect(console.warn.argsForCall.length).toBe(1);
expect(console.warn.argsForCall[0][0]).toBe(
'Warning: Required context `foo` was not specified in `Component`.'
'Warning: Failed Context Types: ' +
'Required context `foo` was not specified in `Component`.'
);
var ComponentInFooStringContext = React.createClass({
@ -193,7 +194,8 @@ describe('ReactContextValidator', function() {
expect(console.warn.argsForCall.length).toBe(2);
expect(console.warn.argsForCall[1][0]).toBe(
'Warning: Invalid context `foo` of type `number` supplied ' +
'Warning: Failed Context Types: ' +
'Invalid context `foo` of type `number` supplied ' +
'to `Component`, expected `string`.' +
' Check the render method of `ComponentInFooNumberContext`.'
);
@ -218,17 +220,20 @@ describe('ReactContextValidator', function() {
ReactTestUtils.renderIntoDocument(<Component testContext={{bar: 123}} />);
expect(console.warn.argsForCall.length).toBe(2);
expect(console.warn.argsForCall[0][0]).toBe(
'Warning: Required child context `foo` was not specified in `Component`.'
'Warning: Failed Context Types: ' +
'Required child context `foo` was not specified in `Component`.'
);
expect(console.warn.argsForCall[1][0]).toBe(
'Warning: Required child context `foo` was not specified in `Component`.'
'Warning: Failed Context Types: ' +
'Required child context `foo` was not specified in `Component`.'
);
ReactTestUtils.renderIntoDocument(<Component testContext={{foo: 123}} />);
expect(console.warn.argsForCall.length).toBe(4);
expect(console.warn.argsForCall[3][0]).toBe(
'Warning: Invalid child context `foo` of type `number` ' +
'Warning: Failed Context Types: ' +
'Invalid child context `foo` of type `number` ' +
'supplied to `Component`, expected `string`.'
);

View File

@ -44,10 +44,7 @@ function getDeclarationErrorAddendum() {
* object keys are not valid. This allows us to keep track of children between
* updates.
*/
var ownerHasKeyUseWarning = {
'react_key_warning': {},
'react_numeric_key_warning': {}
};
var ownerHasKeyUseWarning = {};
var loggedTypeFailures = {};
@ -101,7 +98,6 @@ function validateExplicitKey(element, parentType) {
element._store.validated = true;
warnAndMonitorForKeyUse(
'react_key_warning',
'Each child in an array or iterator should have a unique "key" prop.',
element,
parentType
@ -122,7 +118,6 @@ function validatePropertyKey(name, element, parentType) {
return;
}
warnAndMonitorForKeyUse(
'react_numeric_key_warning',
'Child objects should have non-numeric keys so ordering is preserved.',
element,
parentType
@ -133,17 +128,18 @@ function validatePropertyKey(name, element, parentType) {
* Shared warning and monitoring code for the key warnings.
*
* @internal
* @param {string} warningID The id used when logging.
* @param {string} message The base warning that gets output.
* @param {ReactElement} element Component that requires a key.
* @param {*} parentType element's parent's type.
*/
function warnAndMonitorForKeyUse(warningID, message, element, parentType) {
function warnAndMonitorForKeyUse(message, element, parentType) {
var ownerName = getCurrentOwnerDisplayName();
var parentName = parentType.displayName || parentType.name;
var useName = ownerName || parentName;
var memoizer = ownerHasKeyUseWarning[warningID];
var memoizer = ownerHasKeyUseWarning[message] || (
ownerHasKeyUseWarning[message] = {}
);
if (memoizer.hasOwnProperty(useName)) {
return;
}
@ -166,7 +162,7 @@ function warnAndMonitorForKeyUse(warningID, message, element, parentType) {
}
message += ' See http://fb.me/react-warning-keys for more information.';
warning(false, '%s', warningID + ': ' + message);
warning(false, message);
}
/**

View File

@ -447,10 +447,17 @@ var ReactCompositeComponentMixin = {
if (location === ReactPropTypeLocations.prop) {
// Preface gives us something to blacklist in warning module
var preface = 'Failed CompositeComponent proptype check. ';
warning(false, preface + error.message + addendum);
warning(
false,
'Failed Composite propType: %s',
error.message + addendum
);
} else {
warning(false, error.message + addendum);
warning(
false,
'Failed Context Types: %s',
error.message + addendum
);
}
}
}

View File

@ -13,7 +13,9 @@
var assign = require('Object.assign');
var emptyObject = require('emptyObject');
var monitorCodeUse = require('monitorCodeUse');
var warning = require('warning');
var didWarn = false;
/**
* Keeps track of the current context.
@ -46,7 +48,15 @@ var ReactContext = {
* @return {ReactComponent|array<ReactComponent>}
*/
withContext: function(newContext, scopedCallback) {
monitorCodeUse('react_with_context', {newContext: newContext});
if (__DEV__) {
warning(
didWarn,
'withContext is deprecated and will be removed in a future version. ' +
'Use a wrapper component with getChildContext instead.'
);
didWarn = true;
}
var result;
var previousContext = ReactContext.current;

View File

@ -73,6 +73,12 @@ describe('ReactCompositeComponent', function() {
}
});
// Ignore the first warning which is fired by using withContext at all.
// That way we don't have to reset and assert it on every subsequent test.
// This will be killed soon anyway.
console.warn = mocks.getMockFunction();
React.withContext({}, function() { });
spyOn(console, 'warn');
});
@ -571,8 +577,6 @@ describe('ReactCompositeComponent', function() {
ReactTestUtils.renderIntoDocument(<Component />);
});
// Two warnings, one for the component and one for the div
// We may want to make this expect one warning in the future
expect(console.warn.argsForCall.length).toBe(1);
expect(console.warn.argsForCall[0][0]).toBe(
'Warning: owner-based and parent-based contexts differ '+

View File

@ -12,7 +12,7 @@
'use strict';
var monitorCodeUse = require('monitorCodeUse');
var warning = require('warning');
/**
* Given a `prevElement` and `nextElement`, determines if the existing
@ -57,14 +57,18 @@ function shouldUpdateReactComponent(prevElement, nextElement) {
nextElement.type.displayName != null) {
nextDisplayName = nextElement.type.displayName;
}
monitorCodeUse(
'react_should_update_owner_is_useful',
{
key: prevElement.key,
prevOwner: prevName,
nextOwner: nextName,
nextDisplayName: nextDisplayName
}
warning(
false,
'<%s /> is being rendered by both %s and %s using the same key ' +
'(%s) in the same place. Currently, this means that they ' +
'don\'t preserve state. This behavior should be very rare ' +
'so we\'re considering deprecating it. Please contact the ' +
'React team and explain your use case so that we can take that ' +
'into consideration.',
nextDisplayName || 'Unknown Component',
prevName || '[Unknown]',
nextName || '[Unknown]',
prevElement.key
);
}
}

View File

@ -31,7 +31,14 @@ if (__DEV__) {
);
}
if (format.indexOf('Failed CompositeComponent proptype check. ') === 0) {
if (format.length < 10 || /^[s\W]*$/.test(format)) {
throw new Error(
'The warning format should be able to uniquely identify this ' +
'warning. Please, use a more descriptive format than: ' + format
);
}
if (format.indexOf('Failed Composite propType: ') === 0) {
return; // Ignore CompositeComponent proptype check.
}