Improve error message for nested lazy() and add tests

This commit is contained in:
Dan Abramov
2018-11-21 18:27:18 +00:00
parent 403d2ca028
commit 40d016a5d6
2 changed files with 46 additions and 2 deletions
+13 -1
View File
@@ -54,6 +54,7 @@ import invariant from 'shared/invariant';
import shallowEqual from 'shared/shallowEqual';
import getComponentName from 'shared/getComponentName';
import ReactStrictModeWarnings from './ReactStrictModeWarnings';
import {REACT_LAZY_TYPE} from 'shared/ReactSymbols';
import warning from 'shared/warning';
import warningWithoutStack from 'shared/warningWithoutStack';
import {
@@ -838,14 +839,25 @@ function mountLazyComponent(
break;
}
default: {
let hint = '';
if (__DEV__) {
if (
Component !== null &&
typeof Component === 'object' &&
Component.$$typeof === REACT_LAZY_TYPE
) {
hint = ' Did you wrap a component in React.lazy() more than once?';
}
}
// This message intentionally doesn't mention ForwardRef or MemoComponent
// because the fact that it's a separate type of work is an
// implementation detail.
invariant(
false,
'Element type is invalid. Received a promise that resolves to: %s. ' +
'Lazy element type must resolve to a class or function.',
'Lazy element type must resolve to a class or function.%s',
Component,
hint,
);
}
}
@@ -512,6 +512,35 @@ describe('ReactLazy', () => {
expect(root).toMatchRenderedOutput('Friends Bye');
});
it('throws with a useful error when wrapping invalid type with lazy()', async () => {
const BadLazy = lazy(() => fakeImport(42));
const root = ReactTestRenderer.create(
<Suspense fallback={<Text text="Loading..." />}>
<BadLazy />
</Suspense>,
{
unstable_isConcurrent: true,
},
);
expect(root).toFlushAndYield(['Loading...']);
expect(root).toMatchRenderedOutput(null);
await Promise.resolve();
root.update(
<Suspense fallback={<Text text="Loading..." />}>
<BadLazy />
</Suspense>,
);
expect(() => {
root.unstable_flushAll();
}).toThrow(
'Element type is invalid. Received a promise that resolves to: 42. ' +
'Lazy element type must resolve to a class or function.',
);
});
it('throws with a useful error when wrapping lazy() multiple times', async () => {
const Lazy1 = lazy(() => fakeImport(Text));
const Lazy2 = lazy(() => fakeImport(Lazy1));
@@ -538,7 +567,10 @@ describe('ReactLazy', () => {
root.unstable_flushAll();
}).toThrow(
'Element type is invalid. Received a promise that resolves to: [object Object]. ' +
'Lazy element type must resolve to a class or function.',
'Lazy element type must resolve to a class or function.' +
(__DEV__
? ' Did you wrap a component in React.lazy() more than once?'
: ''),
);
});