Skip to content

Commit f4ee807

Browse files
acdlitesegoddnja
authored andcommitted
Handle errors thrown in gDSFP of a module-style context provider (facebook#13269)
Context should be pushed before calling any user code, so if it errors the stack unwinds correctly.
1 parent d7c57e5 commit f4ee807

File tree

2 files changed

+27
-4
lines changed

2 files changed

+27
-4
lines changed

packages/react-reconciler/src/ReactFiberBeginWork.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,11 @@ function mountIndeterminateComponent(
618618
// Proceed under the assumption that this is a class instance
619619
workInProgress.tag = ClassComponent;
620620

621+
// Push context providers early to prevent context stack mismatches.
622+
// During mounting we don't know the child context yet as the instance doesn't exist.
623+
// We will invalidate the child context in finishClassComponent() right after rendering.
624+
const hasContext = pushLegacyContextProvider(workInProgress);
625+
621626
workInProgress.memoizedState =
622627
value.state !== null && value.state !== undefined ? value.state : null;
623628

@@ -630,10 +635,6 @@ function mountIndeterminateComponent(
630635
);
631636
}
632637

633-
// Push context providers early to prevent context stack mismatches.
634-
// During mounting we don't know the child context yet as the instance doesn't exist.
635-
// We will invalidate the child context in finishClassComponent() right after rendering.
636-
const hasContext = pushLegacyContextProvider(workInProgress);
637638
adoptClassInstance(workInProgress, value);
638639
mountClassInstance(workInProgress, renderExpirationTime);
639640
return finishClassComponent(

packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js

+22
Original file line numberDiff line numberDiff line change
@@ -1469,4 +1469,26 @@ describe('ReactIncrementalErrorHandling', () => {
14691469
ReactNoop.flushDeferredPri();
14701470
expect(ReactNoop.getChildren()).toEqual([span('Caught an error: Hello')]);
14711471
});
1472+
1473+
it('handles error thrown inside getDerivedStateFromProps of a module-style context provider', () => {
1474+
function Provider() {
1475+
return {
1476+
getChildContext() {
1477+
return {foo: 'bar'};
1478+
},
1479+
render() {
1480+
return 'Hi';
1481+
},
1482+
};
1483+
}
1484+
Provider.childContextTypes = {
1485+
x: () => {},
1486+
};
1487+
Provider.getDerivedStateFromProps = () => {
1488+
throw new Error('Oops!');
1489+
};
1490+
1491+
ReactNoop.render(<Provider />);
1492+
expect(() => ReactNoop.flush()).toThrow('Oops!');
1493+
});
14721494
});

0 commit comments

Comments
 (0)