Skip to content

Commit

Permalink
Fix instance where renderToStringAsync returns a promise of a promise (
Browse files Browse the repository at this point in the history
…#378)

* Fix issue where rendered is a promise

I want to test this in my project to see if this change fixes it.

All being well, I'll then add a test here and submit it for review

* Different syntax, but more success

I'm unclear why the previous didn't seem to work for me

* Attempt to write a test for the case based on my app

So far no luck actually reproducing the issue.

I will take a different tact and remove code from my app until the issue
goes away, to figure out what causes the behaviour.

* Add test that tests behaviour

* Further simplify test case

* Further simplify test case

* Create the test I want

* Revert unrelated change

* Add changeset

* Add missing imports

* Reproduce without useClient

But I still need the provider

* Avoid using urql

* Better description

* Update test/compat/async.test.jsx

---------

Co-authored-by: Jovi De Croock <[email protected]>
  • Loading branch information
ccouzens and JoviDeCroock authored Jul 17, 2024
1 parent ae6450b commit 054dae0
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 17 deletions.
5 changes: 5 additions & 0 deletions .changeset/famous-experts-decide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'preact-render-to-string': patch
---

Fix issue where preactRenderToString returns a promise of a promise
2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export async function renderToStringAsync(vnode, context) {
parent[CHILDREN] = [vnode];

try {
const rendered = _renderToString(
const rendered = await _renderToString(
vnode,
context || EMPTY_OBJ,
false,
Expand Down
83 changes: 67 additions & 16 deletions test/compat/async.test.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { renderToStringAsync } from '../../src/index.js';
import { h } from 'preact';
import { Suspense, useId } from 'preact/compat';
import { h, Fragment } from 'preact';
import { Suspense, useId, lazy, createContext } from 'preact/compat';
import { expect } from 'chai';
import { createSuspender } from '../utils.jsx';

Expand All @@ -26,10 +26,14 @@ describe('Async renderToString', () => {
});

it('should render JSX with nested suspended components', async () => {
const { Suspender: SuspenderOne, suspended: suspendedOne } =
createSuspender();
const { Suspender: SuspenderTwo, suspended: suspendedTwo } =
createSuspender();
const {
Suspender: SuspenderOne,
suspended: suspendedOne
} = createSuspender();
const {
Suspender: SuspenderTwo,
suspended: suspendedTwo
} = createSuspender();

const promise = renderToStringAsync(
<ul>
Expand All @@ -56,10 +60,14 @@ describe('Async renderToString', () => {
});

it('should render JSX with nested suspense boundaries', async () => {
const { Suspender: SuspenderOne, suspended: suspendedOne } =
createSuspender();
const { Suspender: SuspenderTwo, suspended: suspendedTwo } =
createSuspender();
const {
Suspender: SuspenderOne,
suspended: suspendedOne
} = createSuspender();
const {
Suspender: SuspenderTwo,
suspended: suspendedTwo
} = createSuspender();

const promise = renderToStringAsync(
<ul>
Expand Down Expand Up @@ -88,12 +96,18 @@ describe('Async renderToString', () => {
});

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 {
Suspender: SuspenderOne,
suspended: suspendedOne
} = createSuspender();
const {
Suspender: SuspenderTwo,
suspended: suspendedTwo
} = createSuspender();
const {
Suspender: SuspenderThree,
suspended: suspendedThree
} = createSuspender();

const promise = renderToStringAsync(
<ul>
Expand Down Expand Up @@ -175,4 +189,41 @@ describe('Async renderToString', () => {
const rendered = await promise;
expect(rendered).to.equal('<p>ok</p>');
});

it('should work with an in-render suspension', async () => {
const Context = createContext();

let c = 0;

const Fetcher = ({ children }) => {
c++;
if (c === 1) {
throw Promise.resolve();
}
return <Fragment>{children}</Fragment>;
};

const LazyComponent = lazy(
async () =>
function ImportedComponent() {
return <div>2</div>;
}
);

const LoadableComponent = ({}) => (
<Suspense fallback={'...loading'}>
<LazyComponent />
</Suspense>
);

const rendered = await renderToStringAsync(
<Context.Provider>
<Fetcher>
<LoadableComponent />
</Fetcher>
</Context.Provider>
);

expect(rendered).to.equal(`<div>2</div>`);
});
});

0 comments on commit 054dae0

Please sign in to comment.