diff --git a/compat/src/suspense.js b/compat/src/suspense.js
index 48c8960996..874e4f4ae1 100644
--- a/compat/src/suspense.js
+++ b/compat/src/suspense.js
@@ -208,18 +208,23 @@ Suspense.prototype.render = function (props, state) {
export function lazy(loader) {
let prom;
- let component;
+ let component = null;
let error;
+ let resolved;
function Lazy(props) {
if (!prom) {
prom = loader();
prom.then(
exports => {
- component = exports.default || exports;
+ if (exports) {
+ component = exports.default || exports;
+ }
+ resolved = true;
},
e => {
error = e;
+ resolved = true;
}
);
}
@@ -228,11 +233,11 @@ export function lazy(loader) {
throw error;
}
- if (!component) {
+ if (!resolved) {
throw prom;
}
- return createElement(component, props);
+ return component ? createElement(component, props) : null;
}
Lazy.displayName = 'Lazy';
diff --git a/compat/test/browser/suspense.test.jsx b/compat/test/browser/suspense.test.jsx
index 727fab65c7..21ec97bff3 100644
--- a/compat/test/browser/suspense.test.jsx
+++ b/compat/test/browser/suspense.test.jsx
@@ -34,9 +34,11 @@ class Catcher extends Component {
}
render(props, state) {
- return state.error
- ?
Catcher did catch: {state.error.message}
- : props.children;
+ return state.error ? (
+ Catcher did catch: {state.error.message}
+ ) : (
+ props.children
+ );
}
}
@@ -104,6 +106,59 @@ describe('suspense', () => {
});
});
+ it('should handle lazy component that rejects without returning a component', async () => {
+ const errorSpy = vi.fn();
+ let renderCount = 0;
+
+ let resolve;
+ function fakeImport() {
+ const p = new Promise((_, reject) => {
+ resolve = () => {
+ reject(new Error('import failed'));
+ return p;
+ };
+ });
+ return p;
+ }
+
+ const SomeComponent = lazy(() =>
+ fakeImport().catch(e => {
+ console.log('caught', e);
+ errorSpy(e);
+ })
+ );
+
+ const App = () => {
+ renderCount++;
+ if (renderCount > 5) {
+ throw new Error('Infinite loop detected!');
+ }
+
+ console.log('RENDER COUNT', renderCount);
+ return (
+
+ loading
}>
+
+
+
+ );
+ };
+
+ render(, scratch);
+ rerender();
+
+ expect(scratch.innerHTML).to.contain('loading');
+
+ const assert = () => {
+ rerender();
+
+ expect(scratch.innerHTML).to.contain('');
+ expect(errorSpy).toHaveBeenCalledOnce;
+ };
+
+ resolve().then(assert).catch(assert);
+ });
+
it('should reset hooks of components', () => {
/** @type {(v) => void} */
let set;
@@ -190,11 +245,13 @@ describe('suspense', () => {
};
}, []);
- return state
- ? {children}
- : ;
+ return state ? (
+ {children}
+ ) : (
+
+ );
};
render(
diff --git a/test/browser/refs.test.jsx b/test/browser/refs.test.jsx
index 5b42406b4f..f4ca6e8a84 100644
--- a/test/browser/refs.test.jsx
+++ b/test/browser/refs.test.jsx
@@ -3,7 +3,7 @@ import { createElement, render, Component, createRef, Fragment } from 'preact';
import { setupScratch, teardown } from '../_util/helpers';
import { vi } from 'vitest';
-// gives call count and argument errors names (otherwise sinon just uses "spy"):
+// gives call count and argument errors names (otherwise vitest just uses "spy"):
let spy = (name, ...args) => {
let spy = vi.fn(...args);
spy.displayName = `spy('${name}')`;
@@ -241,13 +241,15 @@ describe('refs', () => {
it('should correctly set nested child refs', () => {
const ref = createRef();
const App = ({ open }) =>
- open
- ?
- : ;
+ open ? (
+
+ ) : (
+
+ );
render(, scratch);
expect(ref.current).to.not.be.null;
@@ -360,8 +362,39 @@ describe('refs', () => {
render(props, { phase }) {
return (
- {phase === 1
- ?
+ {phase === 1 ? (
+
+
+ r
+ ? calls.push('adding ref to two')
+ : calls.push('removing ref from two')
+ }
+ >
+ Element two
+
+
+ r
+ ? calls.push('adding ref to three')
+ : calls.push('removing ref from three')
+ }
+ >
+ Element three
+
+
+ ) : phase === 2 ? (
+
+
+ r
+ ? calls.push('adding ref to one')
+ : calls.push('removing ref from one')
+ }
+ >
+ Element one
+
+
r
@@ -381,39 +414,8 @@ describe('refs', () => {
Element three
- : phase === 2
- ?
-
- r
- ? calls.push('adding ref to one')
- : calls.push('removing ref from one')
- }
- >
- Element one
-
-
-
- r
- ? calls.push('adding ref to two')
- : calls.push('removing ref from two')
- }
- >
- Element two
-
-
- r
- ? calls.push('adding ref to three')
- : calls.push('removing ref from three')
- }
- >
- Element three
-
-
-
- : null}
+
+ ) : null}
);
}