From cf815872c68b742a9175918865976dae8a83dc9b Mon Sep 17 00:00:00 2001 From: David Dios Date: Tue, 20 Feb 2024 09:32:44 +0000 Subject: [PATCH] fixing multiple suspended child components (#335) --- src/index.js | 32 +++++++++++++++++------------ test/compat/async.test.js | 43 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src/index.js b/src/index.js index debfa618..c52a067f 100644 --- a/src/index.js +++ b/src/index.js @@ -438,9 +438,8 @@ function _renderToString( rendered != null && rendered.type === Fragment && rendered.key == null; rendered = isTopLevelFragment ? rendered.props.children : rendered; - try { - // Recurse into children before invoking the after-diff hook - const str = _renderToString( + const renderChildren = () => + _renderToString( rendered, context, isSvgMode, @@ -448,6 +447,11 @@ function _renderToString( vnode, asyncMode ); + + try { + // Recurse into children before invoking the after-diff hook + const str = renderChildren(); + if (afterDiff) afterDiff(vnode); vnode[PARENT] = undefined; @@ -459,16 +463,18 @@ function _renderToString( if (!error || typeof error.then !== 'function') throw error; - return error.then(() => - _renderToString( - rendered, - context, - isSvgMode, - selectValue, - vnode, - asyncMode - ) - ); + const renderNestedChildren = () => { + try { + return renderChildren(); + } catch (e) { + return e.then( + () => renderChildren(), + () => renderNestedChildren() + ); + } + }; + + return error.then(() => renderNestedChildren()); } } diff --git a/test/compat/async.test.js b/test/compat/async.test.js index 8a9d8299..476ebb99 100644 --- a/test/compat/async.test.js +++ b/test/compat/async.test.js @@ -94,4 +94,47 @@ describe('Async renderToString', () => { expect(rendered).to.equal(expected); }); + + it('should render JSX with multiple suspended direct children within a single suspense boundary', async () => { + const { + Suspender: SuspenderOne, + suspended: suspendedOne + } = createSuspender(); + const { + Suspender: SuspenderTwo, + suspended: suspendedTwo + } = createSuspender(); + const { + Suspender: SuspenderThree, + suspended: suspendedThree + } = createSuspender(); + + const promise = renderToStringAsync( + + ); + + const expected = ``; + + suspendedOne.resolve(); + suspendedTwo.resolve(); + suspendedThree.resolve(); + + const rendered = await promise; + + expect(rendered).to.equal(expected); + }); });