diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index 2f64fb614667b..dcd402072a285 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -618,6 +618,11 @@ function mountIndeterminateComponent( // Proceed under the assumption that this is a class instance workInProgress.tag = ClassComponent; + // Push context providers early to prevent context stack mismatches. + // During mounting we don't know the child context yet as the instance doesn't exist. + // We will invalidate the child context in finishClassComponent() right after rendering. + const hasContext = pushLegacyContextProvider(workInProgress); + workInProgress.memoizedState = value.state !== null && value.state !== undefined ? value.state : null; @@ -630,10 +635,6 @@ function mountIndeterminateComponent( ); } - // Push context providers early to prevent context stack mismatches. - // During mounting we don't know the child context yet as the instance doesn't exist. - // We will invalidate the child context in finishClassComponent() right after rendering. - const hasContext = pushLegacyContextProvider(workInProgress); adoptClassInstance(workInProgress, value); mountClassInstance(workInProgress, renderExpirationTime); return finishClassComponent( diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js index fd5b1c8a33fcd..0b2b6551aa73c 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js @@ -1469,4 +1469,26 @@ describe('ReactIncrementalErrorHandling', () => { ReactNoop.flushDeferredPri(); expect(ReactNoop.getChildren()).toEqual([span('Caught an error: Hello')]); }); + + it('handles error thrown inside getDerivedStateFromProps of a module-style context provider', () => { + function Provider() { + return { + getChildContext() { + return {foo: 'bar'}; + }, + render() { + return 'Hi'; + }, + }; + } + Provider.childContextTypes = { + x: () => {}, + }; + Provider.getDerivedStateFromProps = () => { + throw new Error('Oops!'); + }; + + ReactNoop.render(); + expect(() => ReactNoop.flush()).toThrow('Oops!'); + }); });