Skip to content

Commit cf81587

Browse files
author
David Dios
authored
fixing multiple suspended child components (#335)
1 parent c57b230 commit cf81587

File tree

2 files changed

+62
-13
lines changed

2 files changed

+62
-13
lines changed

src/index.js

+19-13
Original file line numberDiff line numberDiff line change
@@ -438,16 +438,20 @@ function _renderToString(
438438
rendered != null && rendered.type === Fragment && rendered.key == null;
439439
rendered = isTopLevelFragment ? rendered.props.children : rendered;
440440

441-
try {
442-
// Recurse into children before invoking the after-diff hook
443-
const str = _renderToString(
441+
const renderChildren = () =>
442+
_renderToString(
444443
rendered,
445444
context,
446445
isSvgMode,
447446
selectValue,
448447
vnode,
449448
asyncMode
450449
);
450+
451+
try {
452+
// Recurse into children before invoking the after-diff hook
453+
const str = renderChildren();
454+
451455
if (afterDiff) afterDiff(vnode);
452456
vnode[PARENT] = undefined;
453457

@@ -459,16 +463,18 @@ function _renderToString(
459463

460464
if (!error || typeof error.then !== 'function') throw error;
461465

462-
return error.then(() =>
463-
_renderToString(
464-
rendered,
465-
context,
466-
isSvgMode,
467-
selectValue,
468-
vnode,
469-
asyncMode
470-
)
471-
);
466+
const renderNestedChildren = () => {
467+
try {
468+
return renderChildren();
469+
} catch (e) {
470+
return e.then(
471+
() => renderChildren(),
472+
() => renderNestedChildren()
473+
);
474+
}
475+
};
476+
477+
return error.then(() => renderNestedChildren());
472478
}
473479
}
474480

test/compat/async.test.js

+43
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,47 @@ describe('Async renderToString', () => {
9494

9595
expect(rendered).to.equal(expected);
9696
});
97+
98+
it('should render JSX with multiple suspended direct children within a single suspense boundary', async () => {
99+
const {
100+
Suspender: SuspenderOne,
101+
suspended: suspendedOne
102+
} = createSuspender();
103+
const {
104+
Suspender: SuspenderTwo,
105+
suspended: suspendedTwo
106+
} = createSuspender();
107+
const {
108+
Suspender: SuspenderThree,
109+
suspended: suspendedThree
110+
} = createSuspender();
111+
112+
const promise = renderToStringAsync(
113+
<ul>
114+
<Suspense fallback={null}>
115+
<SuspenderOne>
116+
<li>one</li>
117+
</SuspenderOne>
118+
<Suspense fallback={null}>
119+
<SuspenderTwo>
120+
<li>two</li>
121+
</SuspenderTwo>
122+
</Suspense>
123+
<SuspenderThree>
124+
<li>three</li>
125+
</SuspenderThree>
126+
</Suspense>
127+
</ul>
128+
);
129+
130+
const expected = `<ul><li>one</li><li>two</li><li>three</li></ul>`;
131+
132+
suspendedOne.resolve();
133+
suspendedTwo.resolve();
134+
suspendedThree.resolve();
135+
136+
const rendered = await promise;
137+
138+
expect(rendered).to.equal(expected);
139+
});
97140
});

0 commit comments

Comments
 (0)