Skip to content

<Suspense> renders escaped fallback when child evaluates to a falsy value (null) in hono/jsx/streaming #4572

@ciffelia

Description

@ciffelia

What version of Hono are you using?

4.10.8

What runtime/platform is your app running on? (with version if possible)

Bun 1.3.4 (Also reproducible on Cloudflare Workers/Wrangler and Hono Playground)

What steps can reproduce the bug?

When using hono/jsx/streaming, if a <Suspense> component receives a falsy value (such as null resulting from a conditional expression like condition && <Component />) as its child, the streaming renderer incorrectly outputs the fallback content. This outputted fallback is HTML-escaped.

If the child evaluates to null, the component should not suspend, and no content should be rendered within the body of the <Suspense> block.

import { Hono } from "hono";
import { renderToReadableStream, Suspense } from "hono/jsx/streaming";

const app = new Hono();

app.get("/", (c) => {
	const stream = renderToReadableStream(
		<html>
			<body>
				<Suspense fallback={<p>Loading...</p>}>
					{
						// Render AsyncComponent conditionally
						c.req.query("x") === "1" && <AsyncComponent />
					}
				</Suspense>
			</body>
		</html>,
	);

	return c.body(stream, {
		headers: {
			"Content-Type": "text/html; charset=UTF-8",
			"Transfer-Encoding": "chunked",
		},
	});
});

const AsyncComponent = async () => {
	await new Promise((resolve) => setTimeout(resolve, 50));
	return <p>Complete!</p>;
};

export default app;
import { expect, test } from "bun:test";
import app from "./index";

test("/", async () => {
	const res = await app.request("/");
	expect(await res.text()).toBe(`<html><body></body></html>`);
});

What is the expected behavior?

<html><body></body></html>

What do you see instead?

<html><body>&lt;p&gt;Loading...&lt;/p&gt;</body></html>

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions