diff --git a/runtime_tests/deno-jsx/jsx.test.tsx b/runtime_tests/deno-jsx/jsx.test.tsx index 6e4580fc6..d4883b507 100644 --- a/runtime_tests/deno-jsx/jsx.test.tsx +++ b/runtime_tests/deno-jsx/jsx.test.tsx @@ -28,6 +28,12 @@ Deno.test('JSX: Fragment', () => { assertEquals(fragment.toString(), '

1

2

') }) +Deno.test('JSX: Empty Fragment', () => { + const Component = () => <> + const html = + assertEquals(html.toString(), '') +}) + Deno.test('JSX: Async Component', async () => { const Component = async ({ name }: { name: string }) => new Promise((resolve) => setTimeout(() => resolve({name}), 10)) diff --git a/src/jsx/base.ts b/src/jsx/base.ts index 0f4b7e861..603b09394 100644 --- a/src/jsx/base.ts +++ b/src/jsx/base.ts @@ -15,7 +15,7 @@ import { domRenderers } from './intrinsic-element/common' // eslint-disable-next-line @typescript-eslint/no-explicit-any export type Props = Record export type FC

= { - (props: P): HtmlEscapedString | Promise + (props: P): HtmlEscapedString | Promise | null defaultProps?: Partial

| undefined displayName?: string | undefined } @@ -247,7 +247,10 @@ class JSXFunctionNode extends JSXNode { children: children.length <= 1 ? children[0] : children, }) - if (res instanceof Promise) { + if (typeof res === 'boolean' || res == null) { + // boolean or null or undefined + return + } else if (res instanceof Promise) { if (globalContexts.length === 0) { buffer.unshift('', res) } else { @@ -371,11 +374,11 @@ export const memo = ( component: FC, propsAreEqual: (prevProps: Readonly, nextProps: Readonly) => boolean = shallowEqual ): FC => { - let computed: HtmlEscapedString | Promise | undefined = undefined + let computed: ReturnType> = null let prevProps: T | undefined = undefined - return ((props: T & { children?: Child }): HtmlEscapedString | Promise => { + return ((props) => { if (prevProps && !propsAreEqual(prevProps, props)) { - computed = undefined + computed = null } prevProps = props return (computed ||= component(props)) diff --git a/src/jsx/index.test.tsx b/src/jsx/index.test.tsx index bc1c09119..1fb7063e2 100644 --- a/src/jsx/index.test.tsx +++ b/src/jsx/index.test.tsx @@ -383,6 +383,24 @@ describe('render to string', () => { 'Home page

Hono

Hono is great

' ) }) + + describe('Booleans, Null, and Undefined Are Ignored', () => { + it.each([true, false, undefined, null])('%s', (item) => { + const Component: FC = (() => { + return item + }) as FC + const template = + expect(template.toString()).toBe('') + }) + + it('falsy value', () => { + const Component: FC = (() => { + return 0 + }) as unknown as FC + const template = + expect(template.toString()).toBe('0') + }) + }) }) describe('style attribute', () => {