Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add component stack to invariant #11652

Closed
3 changes: 2 additions & 1 deletion packages/react-dom/src/client/ReactDOMFiberInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,8 @@ function updateNamedCousins(rootNode, props) {
invariant(
otherProps,
'ReactDOMInput: Mixing React and non-React radio inputs with the ' +
'same `name` is not supported.',
'same `name` is not supported.%s',
getCurrentFiberStackAddendum() || '',
);

// We need update the tracked value on the named cousin since the value
Expand Down
3 changes: 2 additions & 1 deletion packages/react-dom/src/client/ReactDOMFiberTextarea.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export function getHostProps(element: Element, props: Object) {
const node = ((element: any): TextAreaWithWrapperState);
invariant(
props.dangerouslySetInnerHTML == null,
'`dangerouslySetInnerHTML` does not make sense on <textarea>.',
'`dangerouslySetInnerHTML` does not make sense on <textarea>.%s',
getCurrentFiberStackAddendum() || '',
);

// Always set children to the same thing. In IE9, the selection range will
Expand Down
24 changes: 14 additions & 10 deletions packages/react-reconciler/src/ReactChildFiber.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ if (__DEV__) {
'Each child in an array or iterator should have a unique ' +
'"key" prop. See https://fb.me/react-warning-keys for ' +
'more information.%s',
getCurrentFiberStackAddendum(),
getCurrentFiberStackAddendum() || '',
);
};
}
Expand All @@ -109,8 +109,9 @@ function coerceRef(current: Fiber | null, element: ReactElement) {
invariant(
inst,
'Missing owner for string ref %s. This error is likely caused by a ' +
'bug in React. Please file an issue.',
'bug in React. Please file an issue.%s',
mixedRef,
getCurrentFiberStackAddendum() || '',
);
const stringRef = '' + mixedRef;
// Check if previous string ref matches new string ref
Expand All @@ -134,7 +135,8 @@ function coerceRef(current: Fiber | null, element: ReactElement) {
} else {
invariant(
typeof mixedRef === 'string',
'Expected ref to be a function or a string.',
'Expected ref to be a function or a string.%s',
getCurrentFiberStackAddendum() || '',
);
invariant(
element._owner,
Expand All @@ -143,8 +145,9 @@ function coerceRef(current: Fiber | null, element: ReactElement) {
'1. You may be adding a ref to a functional component\n' +
"2. You may be adding a ref to a component that was not created inside a component's render method\n" +
'3. You have multiple copies of React loaded\n' +
'See https://fb.me/react-refs-must-have-owner for more information.',
'See https://fb.me/react-refs-must-have-owner for more information.%s',
mixedRef,
getCurrentFiberStackAddendum() || '',
);
}
}
Expand All @@ -157,16 +160,16 @@ function throwOnInvalidObjectType(returnFiber: Fiber, newChild: Object) {
if (__DEV__) {
addendum =
' If you meant to render a collection of children, use an array ' +
'instead.' +
(getCurrentFiberStackAddendum() || '');
'instead.';
}
invariant(
false,
'Objects are not valid as a React child (found: %s).%s',
'Objects are not valid as a React child (found: %s).%s%s',
Object.prototype.toString.call(newChild) === '[object Object]'
? 'object with keys {' + Object.keys(newChild).join(', ') + '}'
: newChild,
addendum,
getCurrentFiberStackAddendum() || '',
);
}
}
Expand Down Expand Up @@ -680,7 +683,7 @@ function ChildReconciler(shouldTrackSideEffects) {
'duplicated and/or omitted — the behavior is unsupported and ' +
'could change in a future version.%s',
key,
getCurrentFiberStackAddendum(),
getCurrentFiberStackAddendum() || '',
);
break;
default:
Expand Down Expand Up @@ -862,7 +865,8 @@ function ChildReconciler(shouldTrackSideEffects) {
invariant(
typeof iteratorFn === 'function',
'An object is not an iterable. This error is likely caused by a bug in ' +
'React. Please file an issue.',
'React. Please file an issue.%s',
getCurrentFiberStackAddendum() || '',
);

if (__DEV__) {
Expand All @@ -875,7 +879,7 @@ function ChildReconciler(shouldTrackSideEffects) {
'Using Maps as children is unsupported and will likely yield ' +
'unexpected results. Convert it to a sequence/iterable of keyed ' +
'ReactElements instead.%s',
getCurrentFiberStackAddendum(),
getCurrentFiberStackAddendum() || '',
);
didWarnAboutMaps = true;
}
Expand Down
6 changes: 5 additions & 1 deletion packages/react-reconciler/src/ReactFiber.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import type {TypeOfInternalContext} from './ReactTypeOfInternalContext';
import type {TypeOfSideEffect} from 'shared/ReactTypeOfSideEffect';
import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {UpdateQueue} from './ReactFiberUpdateQueue';
import ReactDebugCurrentFiber from './ReactDebugCurrentFiber';

const {getCurrentFiberStackAddendum} = ReactDebugCurrentFiber;

import invariant from 'fbjs/lib/invariant';
import {NoEffect} from 'shared/ReactTypeOfSideEffect';
Expand Down Expand Up @@ -390,9 +393,10 @@ export function createFiberFromElement(
false,
'Element type is invalid: expected a string (for built-in ' +
'components) or a class/function (for composite components) ' +
'but got: %s.%s',
'but got: %s.%s%s',
type == null ? type : typeof type,
info,
getCurrentFiberStackAddendum() || '',
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,21 @@ describe('ReactIncrementalErrorHandling', () => {
return {type: 'span', children: [], prop};
}

function removeStack(str) {
return str && str.replace(/in .+? \(at .+?:\d+\)/g, '').trim();
}

function stripStackTrace(compSpan) {
let [first, ...rest] = compSpan;
return [
...rest,
{
...first,
prop: removeStack(first.prop) || '',
},
];
}

it('catches render error in a boundary during full deferred mounting', () => {
class ErrorBoundary extends React.Component {
state = {error: null};
Expand Down Expand Up @@ -745,7 +760,7 @@ describe('ReactIncrementalErrorHandling', () => {
expect(ReactNoop.flush).toWarnDev(
'Warning: React.createElement: type is invalid -- expected a string',
);
expect(ReactNoop.getChildren()).toEqual([
expect(stripStackTrace(ReactNoop.getChildren())).toEqual([
span(
'Element type is invalid: expected a string (for built-in components) or ' +
'a class/function (for composite components) but got: undefined.' +
Expand Down Expand Up @@ -792,7 +807,7 @@ describe('ReactIncrementalErrorHandling', () => {
expect(ReactNoop.flush).toWarnDev(
'Warning: React.createElement: type is invalid -- expected a string',
);
expect(ReactNoop.getChildren()).toEqual([
expect(stripStackTrace(ReactNoop.getChildren())).toEqual([
span(
'Element type is invalid: expected a string (for built-in components) or ' +
'a class/function (for composite components) but got: undefined.' +
Expand Down