diff --git a/compat/src/suspense.js b/compat/src/suspense.js index 32cc3dfd75..3bb60c9eb0 100644 --- a/compat/src/suspense.js +++ b/compat/src/suspense.js @@ -57,6 +57,9 @@ function detachedClone(vnode, detachedParent, parentDom) { if (vnode._component._parentDom === parentDom) { vnode._component._parentDom = detachedParent; } + + vnode._component._force = true; + vnode._component = null; } diff --git a/compat/test/browser/suspense.test.js b/compat/test/browser/suspense.test.js index d970cd0076..d18dc8104f 100644 --- a/compat/test/browser/suspense.test.js +++ b/compat/test/browser/suspense.test.js @@ -1,4 +1,4 @@ -import { setupRerender } from 'preact/test-utils'; +import { act, setupRerender } from 'preact/test-utils'; import React, { createElement, render, @@ -9,7 +9,8 @@ import React, { createContext, useState, useEffect, - useLayoutEffect + useLayoutEffect, + memo } from 'preact/compat'; import { setupScratch, teardown } from '../../../test/_util/helpers'; import { createLazy, createSuspender } from './suspense-utils'; @@ -1501,8 +1502,8 @@ describe('suspense', () => { /** @type {() => void} */ let hide, - /** @type {(v) => void} */ - setValue; + /** @type {(v) => void} */ + setValue; class Conditional extends Component { constructor(props) { @@ -2159,4 +2160,57 @@ describe('suspense', () => { expect(scratch.innerHTML).to.equal('

hello world

'); }); }); + + it('should re-execute descendant memoed component effect when lazy boundary resolves', async () => { + const MemodComp = memo(() => { + const [state, setState] = useState('Memod effect not executed'); + useEffect(() => { + setState('Memod effect executed'); + }, []); + return {state}; + }); + + const NormalComp = () => { + const [state, setState] = useState('effect not executed'); + useEffect(() => { + setState('effect executed'); + }, []); + return {state}; + }; + + /** @type {() => Promise} */ + let resolve; + const LazyComp = lazy(() => { + const p = new Promise(res => { + resolve = () => { + res({ default: NormalComp }); + return p; + }; + }); + + return p; + }); + + render( + Suspended...}> +
+ + +
+
, + scratch + ); + + rerender(); + + expect(scratch.innerHTML).to.eql(`
Suspended...
`); + + await resolve(); + + await act(() => rerender()); + + return expect(scratch.innerHTML).to.eql( + `
Memod effect executedeffect executed
` + ); + }); });