If you are using the JSX Renderer middleware, you can nest layouts using <Layout />.
import { const jsxRenderer: (component?: ComponentWithChildren, options?: RendererOptions) => MiddlewareHandlerJSX Renderer Middleware for hono.jsxRenderer } from 'hono/jsx-renderer'
export default function jsxRenderer(component?: ComponentWithChildren, options?: RendererOptions): MiddlewareHandlerJSX Renderer Middleware for hono.jsxRenderer(({ children: Childchildren, type Layout: FCLayout }) => {
return (
<type Layout: FCLayout>
<JSX.IntrinsicElements.nav: JSX.HTMLAttributesnav>Posts Menu</JSX.IntrinsicElements.nav: JSX.HTMLAttributesnav>
<JSX.IntrinsicElements.div: JSX.HTMLAttributesdiv>{children: Childchildren}</JSX.IntrinsicElements.div: JSX.HTMLAttributesdiv>
</type Layout: FCLayout>
)
})
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: stringtitle: 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.HTMLAttributesdiv>Content</JSX.IntrinsicElements.div: JSX.HTMLAttributesdiv>, { title: stringtitle: '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: stringtitle: string }
): Response
}
}
import { const jsxRenderer: (component?: ComponentWithChildren, options?: RendererOptions) => MiddlewareHandlerJSX Renderer Middleware for hono.jsxRenderer } from 'hono/jsx-renderer'
export default function jsxRenderer(component?: ComponentWithChildren, options?: RendererOptions): MiddlewareHandlerJSX Renderer Middleware for hono.jsxRenderer(({ children: Childchildren, type Layout: FCLayout, title: stringtitle }) => {
return (
<type Layout: FCLayout title: stringtitle={title: stringtitle}>
{/* Pass the title prop to the parent renderer */}
<JSX.IntrinsicElements.main: JSX.HTMLAttributesmain>{children: Childchildren}</JSX.IntrinsicElements.main: JSX.HTMLAttributesmain>
</type Layout: FCLayout>
)
})
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: stringtitle: string }
): Response
}
}
import { const jsxRenderer: (component?: ComponentWithChildren, options?: RendererOptions) => MiddlewareHandlerJSX Renderer Middleware for hono.jsxRenderer } from 'hono/jsx-renderer'
export default function jsxRenderer(component?: ComponentWithChildren, options?: RendererOptions): MiddlewareHandlerJSX Renderer Middleware for hono.jsxRenderer(({ children: Childchildren, title: stringtitle }) => {
return (
<JSX.IntrinsicElements.html: HtmlHTMLAttributeshtml JSX.HTMLAttributes.lang?: string | undefinedlang='en'>
<JSX.IntrinsicElements.head: JSX.HTMLAttributeshead>
<JSX.IntrinsicElements.title: JSX.HTMLAttributestitle>{title: stringtitle}</JSX.IntrinsicElements.title: JSX.HTMLAttributestitle> {/* Use the title prop here */}
</JSX.IntrinsicElements.head: JSX.HTMLAttributeshead>
<JSX.IntrinsicElements.body: JSX.HTMLAttributesbody>
{children: Childchildren} {/* Insert the Layout's children here */}
</JSX.IntrinsicElements.body: JSX.HTMLAttributesbody>
</JSX.IntrinsicElements.html: HtmlHTMLAttributeshtml>
)
})