Skip to content

Commit 10a7a5b

Browse files
authored
Fix synchronous thenable rejection (#14633)
* Fix handling of sync rejection Reverts #14632 and adds a regression test. * Handle rejection synchronously too Fewer footguns and seems like nicer behavior anyway.
1 parent a2fa6eb commit 10a7a5b

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

packages/react-reconciler/src/ReactFiberLazyComponent.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,12 @@ export function readLazyComponentType<T>(lazyComponent: LazyComponent<T>): T {
7373
}
7474
},
7575
);
76-
// Check if it resolved synchronously
77-
if (lazyComponent._status === Resolved) {
78-
return lazyComponent._result;
76+
// Handle synchronous thenables.
77+
switch (lazyComponent._status) {
78+
case Resolved:
79+
return lazyComponent._result;
80+
case Rejected:
81+
throw lazyComponent._result;
7982
}
8083
lazyComponent._result = thenable;
8184
throw thenable;

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

+30
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,36 @@ describe('ReactLazy', () => {
7878
expect(root).toMatchRenderedOutput('Hi');
7979
});
8080

81+
it('can reject synchronously without suspending', async () => {
82+
const LazyText = lazy(() => ({
83+
then(resolve, reject) {
84+
reject(new Error('oh no'));
85+
},
86+
}));
87+
88+
class ErrorBoundary extends React.Component {
89+
state = {};
90+
static getDerivedStateFromError(error) {
91+
return {message: error.message};
92+
}
93+
render() {
94+
return this.state.message
95+
? `Error: ${this.state.message}`
96+
: this.props.children;
97+
}
98+
}
99+
100+
const root = ReactTestRenderer.create(
101+
<ErrorBoundary>
102+
<Suspense fallback={<Text text="Loading..." />}>
103+
<LazyText text="Hi" />
104+
</Suspense>
105+
</ErrorBoundary>,
106+
);
107+
expect(ReactTestRenderer).toHaveYielded([]);
108+
expect(root).toMatchRenderedOutput('Error: oh no');
109+
});
110+
81111
it('multiple lazy components', async () => {
82112
function Foo() {
83113
return <Text text="Foo" />;

0 commit comments

Comments
 (0)