If you are using the JSX Renderer middleware, you can nest layouts using <Layout />
.
import { const jsxRenderer: (component?: ComponentWithChildren, options?: RendererOptions) => MiddlewareHandler
JSX Renderer Middleware for hono.jsxRenderer } from 'hono/jsx-renderer'
export default function jsxRenderer(component?: ComponentWithChildren, options?: RendererOptions): MiddlewareHandler
JSX Renderer Middleware for hono.jsxRenderer(({ children: Child
children, type Layout: FC
Layout }) => {
return (
<type Layout: FC
Layout>
<JSX.IntrinsicElements.nav: JSX.HTMLAttributes
nav>Posts Menu</JSX.IntrinsicElements.nav: JSX.HTMLAttributes
nav>
<JSX.IntrinsicElements.div: JSX.HTMLAttributes
div>{children: Child
children}</JSX.IntrinsicElements.div: JSX.HTMLAttributes
div>
</type Layout: FC
Layout>
)
})
Props passed to nested renderers do not automatically propagate to the parent renderers. To ensure that the parent layouts receive the necessary props, you should explicitly pass them from the nested <Layout />
component. Here's how you can achieve that:
Let's start with our route handler:
import type { class Context<E extends Env = any, P extends string = any, I extends Input = {}>
Context } from 'hono'
declare module 'hono' {
interface ContextRenderer {
(
content: string | Promise<string>
content: string | interface Promise<T>
Represents the completion of an asynchronous operationPromise<string>,
props: {
title: string;
}
props: { title: string
title: string }
): Response
}
}
import { const createRoute: CreateHandlersInterface<Env, any>
createRoute } from 'honox/factory'
export default createRoute<{}, Response, any>(handler1: H<any, any, {}, Response>): [H<any, any, {}, Response>] (+9 overloads)
createRoute((c: Context<any, any, {}>
c: class Context<E extends Env = any, P extends string = any, I extends Input = {}>
Context) => {
return c: Context<any, any, {}>
c.Context<any, any, {}>.render: ContextRenderer
(content: string | Promise<string>, props: {
title: string;
}) => Response
`.render()` can create a response within a layout.render(<JSX.IntrinsicElements.div: JSX.HTMLAttributes
div>Content</JSX.IntrinsicElements.div: JSX.HTMLAttributes
div>, { title: string
title: 'Dashboard' })
})
Now, let's take a look at our nested renderer:
// @filename: app/routes/nested/_renderer.tsx
/** @jsx jsx */
/** @jsxImportSource hono/jsx */
import 'hono'
declare module 'hono' {
interface ContextRenderer {
(
content: string | Promise<string>
content: string | interface Promise<T>
Represents the completion of an asynchronous operationPromise<string>,
props: {
title: string;
}
props: { title: string
title: string }
): Response
}
}
import { const jsxRenderer: (component?: ComponentWithChildren, options?: RendererOptions) => MiddlewareHandler
JSX Renderer Middleware for hono.jsxRenderer } from 'hono/jsx-renderer'
export default function jsxRenderer(component?: ComponentWithChildren, options?: RendererOptions): MiddlewareHandler
JSX Renderer Middleware for hono.jsxRenderer(({ children: Child
children, type Layout: FC
Layout, title: string
title }) => {
return (
<type Layout: FC
Layout title: string
title={title: string
title}>
{/* Pass the title prop to the parent renderer */}
<JSX.IntrinsicElements.main: JSX.HTMLAttributes
main>{children: Child
children}</JSX.IntrinsicElements.main: JSX.HTMLAttributes
main>
</type Layout: FC
Layout>
)
})
In this setup, all the props sent to the nested renderer's <Layout />
are consumed by the parent renderer:
// @filename: app/routes/_renderer.tsx
/** @jsx jsx */
/** @jsxImportSource hono/jsx */
import 'hono'
declare module 'hono' {
interface ContextRenderer {
(
content: string | Promise<string>
content: string | interface Promise<T>
Represents the completion of an asynchronous operationPromise<string>,
props: {
title: string;
}
props: { title: string
title: string }
): Response
}
}
import { const jsxRenderer: (component?: ComponentWithChildren, options?: RendererOptions) => MiddlewareHandler
JSX Renderer Middleware for hono.jsxRenderer } from 'hono/jsx-renderer'
export default function jsxRenderer(component?: ComponentWithChildren, options?: RendererOptions): MiddlewareHandler
JSX Renderer Middleware for hono.jsxRenderer(({ children: Child
children, title: string
title }) => {
return (
<JSX.IntrinsicElements.html: HtmlHTMLAttributes
html JSX.HTMLAttributes.lang?: string | undefined
lang='en'>
<JSX.IntrinsicElements.head: JSX.HTMLAttributes
head>
<JSX.IntrinsicElements.title: JSX.HTMLAttributes
title>{title: string
title}</JSX.IntrinsicElements.title: JSX.HTMLAttributes
title> {/* Use the title prop here */}
</JSX.IntrinsicElements.head: JSX.HTMLAttributes
head>
<JSX.IntrinsicElements.body: JSX.HTMLAttributes
body>
{children: Child
children} {/* Insert the Layout's children here */}
</JSX.IntrinsicElements.body: JSX.HTMLAttributes
body>
</JSX.IntrinsicElements.html: HtmlHTMLAttributes
html>
)
})