diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index 57a86e6984d8..e5d87e5c3d22 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -116,7 +116,11 @@ import shallowEqual from 'shared/shallowEqual'; import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber'; import getComponentNameFromType from 'shared/getComponentNameFromType'; import ReactStrictModeWarnings from './ReactStrictModeWarnings'; -import {REACT_LAZY_TYPE, getIteratorFn} from 'shared/ReactSymbols'; +import { + REACT_LAZY_TYPE, + REACT_PROVIDER_TYPE, + getIteratorFn, +} from 'shared/ReactSymbols'; import { getCurrentFiberOwnerNameInDevOrNull, setIsRendering, @@ -1831,12 +1835,13 @@ function mountLazyComponent( } 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?'; + if (Component !== null && typeof Component === 'object') { + if (Component.$$typeof === REACT_LAZY_TYPE) { + hint = ' Did you wrap a component in React.lazy() more than once?'; + } else if (Component.type.$$typeof === REACT_PROVIDER_TYPE) { + hint = + ' Context Providers cannot be lazily rendered without being wrapped in a component.'; + } } } diff --git a/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js b/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js index a96c60bc26e8..a79b2316f093 100644 --- a/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js @@ -783,6 +783,37 @@ describe('ReactLazy', () => { ); }); + it('throws with a useful error when rendering a context Provider', async () => { + const ctx = React.createContext(null); + const Provider = ; + const BadLazy = lazy(() => fakeImport(Provider)); + + const root = ReactTestRenderer.create( + }> + + , + { + unstable_isConcurrent: true, + }, + ); + + await waitForAll(['Loading...']); + + await resolveFakeImport(Provider); + root.update( + }> + + , + ); + await waitForThrow( + 'Element type is invalid. Received a promise that resolves to: [object Object]. ' + + 'Lazy element type must resolve to a class or function.' + + (__DEV__ + ? ' Context Providers cannot be lazily rendered without being wrapped in a component.' + : ''), + ); + }); + it('warns about defining propTypes on the outer wrapper', () => { const LazyText = lazy(() => fakeImport(Text)); expect(() => {