@samitouri / QOS-React-2 / commits / 10a7a5b5ce

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.

Dan Abramov committed Jan 19, 2019 at 00:42 UTC 10a7a5b5ced683125d68584a78084faac3197846
2 files changed +36 -3
packages/react-reconciler/src/ReactFiberLazyComponent.js
+6 -3
@@ -73,9 +73,12 @@ export function readLazyComponentType<T>(lazyComponent: LazyComponent<T>): T {
73 }
74 },
75 );
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;
82 }
83 lazyComponent._result = thenable;
84 throw thenable;
packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js
+30
@@ -78,6 +78,36 @@ describe('ReactLazy', () => {
78 expect(root).toMatchRenderedOutput('Hi');
79 });
80
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 +
111 it('multiple lazy components', async () => {
112 function Foo() {
113 return <Text text="Foo" />;