new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Hono · all subjects

jsx

58 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Counter component example with hono/jsx/dom

import { useState } from 'hono/jsx' import { render } from 'hono/jsx/dom' function Counter() { const [count, setCount] = useState(0) return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ) } function App() { return ( <html> <body> <Counter /> </body> </html> ) } const root = document.getElementById('root') render(<App />, root)

hono/jsx/dom client-side JSX

hono/jsx supports client-side interactive UI in the browser through Client Components or hono/jsx/dom. A counter program in hono/jsx/dom is only 2.8KB with Brotli compression, compared to 47.8KB for React.

render() function for mounting components

The render() function inserts JSX components within a specified HTML element. It takes the component and a container element as arguments: render(<Component />, container).

React-compatible hooks in hono/jsx/dom

hono/jsx/dom provides the following hooks that are compatible or partially compatible with React: useState(), useEffect(), useRef(), useCallback(), use(), startTransition(), useTransition(), useDeferredValue(), useMemo(), useLayoutEffect(), useReducer(), useDebugValue(), createElement(), memo(), isValidElement(), useId(), createRef(), forwardRef(), useImperativeHandle(), useSyncExternalStore(), useInsertionEffect(), useFormStatus(), useActionState(), and useOptimistic().

startViewTransition() function

The startViewTransition() function wraps document.startViewTransition for a shorter syntax when handling View Transitions API. It takes a callback function that updates state or performs DOM changes within the transition.

viewTransition() CSS helper function

The viewTransition() function from hono/jsx/dom/css generates a unique view-transition-name that can be used in CSS with keyframes. It converts ::view-transition-old() and ::view-transition-new() pseudo-elements automatically.

useViewTransition() hook

The useViewTransition() hook returns a tuple of [boolean, (callback: () => void) => void] representing the isUpdating flag and startViewTransition() function. The component is evaluated when startViewTransition() is called and when the finish promise becomes fulfilled. This allows conditional styling only during the animation.

Configure hono/jsx/dom in tsconfig.json

To use the smaller hono/jsx/dom runtime instead of hono/jsx, set jsxImportSource to "hono/jsx/dom" and jsx to "react-jsx" in tsconfig.json compilerOptions.

Configure hono/jsx/dom in vite.config.ts

Alternatively, specify hono/jsx/dom for JSX transformation in vite.config.ts by setting jsxImportSource to "hono/jsx/dom" in the esbuild options.

Render JSX with c.html()

Use c.html() to render JSX components in route handlers. Pass the JSX element as an argument: return c.html(<ComponentName prop={value} />)

JSX tsconfig.json configuration

To use JSX in Hono, modify tsconfig.json with these compiler options: "jsx": "react-jsx" and "jsxImportSource": "hono/jsx". Alternatively, use pragma directives /** @jsx jsx */ and /** @jsxImportSource hono/jsx */ at the top of files.

JSX configuration for Deno

For Deno, modify deno.json instead of tsconfig.json with compiler options: "jsx": "precompile" and "jsxImportSource": "@hono/hono/jsx".

JSX file extension requirement

When using JSX with Hono, change the main file extension from .ts to .tsx. Also update package.json (or deno.json) dev scripts to reflect this change, for example from "bun run --hot src/index.ts" to "bun run --hot src/index.tsx".

JSX component with FC type

Import FC from 'hono/jsx' to type functional components. FC is the functional component type that can include generic type parameters for props. Example: const MyComponent: FC<{ messages: string[] }> = (props) => { return ... }

Metadata hoisting in JSX

Document metadata tags such as <title>, <link>, and <meta> can be written directly inside components and will be automatically hoisted to the <head> section of the document. When hoisting occurs, existing elements are not removed; elements appearing later are added to the end.

Fragment and empty tag syntax

Use Fragment from 'hono/jsx' or <></> syntax to group multiple elements without adding extra nodes. Both approaches work: <Fragment> ... </Fragment> or <> ... </>

PropsWithChildren type

Import PropsWithChildren from 'hono/jsx' to correctly infer child elements in function components. Usage: function Component({ title, children }: PropsWithChildren<CustomType>) { ... }

dangerouslySetInnerHTML for raw HTML

To directly insert raw HTML in JSX, use the dangerouslySetInnerHTML attribute with an object containing __html property: const inner = { __html: 'JSX &middot; SSR' }; const element = <div dangerouslySetInnerHTML={inner} />

memo for component memoization

Import memo from 'hono/jsx' to optimize components by memoizing computed strings. Usage: const Header = memo(() => <header>Welcome to Hono</header>)

useContext for sharing data across component tree

Use createContext and useContext from 'hono/jsx' to share data globally across component trees without passing values through props. Create context with createContext(), access it with useContext(), and provide values with Context.Provider component.

Async components in JSX

hono/jsx supports async components using async/await syntax. When rendering with c.html(), async components are automatically awaited. Example: const AsyncComponent = async () => { await delay(); return <div>Done!</div> }

Suspense for streaming components

Use Suspense from 'hono/jsx/streaming' to wrap async components for streaming. Content in fallback renders first, then awaited content displays once the Promise resolves. Must use renderToReadableStream() for rendering. Mark as experimental feature.

renderToReadableStream for streaming

Import renderToReadableStream from 'hono/jsx/streaming' to render JSX to a readable stream. Use with Suspense for streaming support. Return with c.body() setting headers 'Content-Type': 'text/html; charset=UTF-8' and 'Transfer-Encoding': 'chunked'.

ErrorBoundary for error handling

Use ErrorBoundary component to catch errors in child components. Specify fallback content to display if an error occurs. ErrorBoundary works with both sync and async components, and can be combined with Suspense. Mark as experimental feature.

StreamingContext for streaming configuration

Use StreamingContext from 'hono/jsx/streaming' to provide configuration for streaming components like Suspense and ErrorBoundary. Useful for adding nonce values to script tags generated by these components for Content Security Policy (CSP). Set scriptNonce value that is automatically added to <script> tags. Mark as experimental feature.

JSX with html middleware

Combine JSX and html middleware (from 'hono/html') for powerful templating. The html middleware can be used alongside JSX components for template creation.

JSX Renderer Middleware

The JSX Renderer Middleware allows creating HTML pages more easily with JSX, providing a built-in middleware for JSX rendering.

Override JSX type definitions

Override JSX type definitions to add custom elements and attributes by declaring module 'hono/jsx' with custom IntrinsicElements in the JSX namespace. Example: declare module 'hono/jsx' { namespace JSX { interface IntrinsicElements { 'my-custom-element': HTMLAttributes & { 'x-event'?: 'click' | 'scroll' } } } }

Example: Basic JSX with Hono

import { Hono } from 'hono' import type { FC } from 'hono/jsx' const app = new Hono() const Layout: FC = (props) => { return ( <html> <body>{props.children}</body> </html> ) } const Top: FC<{ messages: string[] }> = (props: { messages: string[] }) => { return ( <Layout> <h1>Hello Hono!</h1> <ul> {props.messages.map((message) => { return <li>{message}!!</li> })} </ul> </Layout> ) } app.get('/', (c) => { const messages = ['Good Morning', 'Good Evening', 'Good Night'] return c.html(<Top messages={messages} />) }) export default app

Example: Metadata hoisting with setRenderer

import { Hono } from 'hono' const app = new Hono() app.use('*', async (c, next) => { c.setRenderer((content) => { return c.html( <html> <head></head> <body>{content}</body> </html> ) }) await next() }) app.get('/about', (c) => { return c.render( <> <title>About Page</title> <meta name='description' content='This is the about page.' /> about page content </> ) }) export default app

Example: Context usage in JSX

import type { FC } from 'hono/jsx' import { createContext, useContext } from 'hono/jsx' const themes = { light: { color: '#000000', background: '#eeeeee' }, dark: { color: '#ffffff', background: '#222222' }, } const ThemeContext = createContext(themes.light) const Button: FC = () => { const theme = useContext(ThemeContext) return <button style={theme}>Push!</button> } const Toolbar: FC = () => { return ( <div> <Button /> </div> ) } app.get('/', (c) => { return c.html( <div> <ThemeContext.Provider value={themes.dark}> <Toolbar /> </ThemeContext.Provider> </div> ) })

Example: Async component with Suspense

import { renderToReadableStream, Suspense } from 'hono/jsx/streaming' const AsyncComponent = async () => { await new Promise((r) => setTimeout(r, 1000)) return <div>Done!</div> } app.get('/', (c) => { const stream = renderToReadableStream( <html> <body> <Suspense fallback={<div>loading...</div>}> <AsyncComponent /> </Suspense> </body> </html> ) return c.body(stream, { headers: { 'Content-Type': 'text/html; charset=UTF-8', 'Transfer-Encoding': 'chunked', }, }) })

Example: ErrorBoundary usage

function SyncComponent() { throw new Error('Error') return <div>Hello</div> } app.get('/sync', async (c) => { return c.html( <html> <body> <ErrorBoundary fallback={<div>Out of Service</div>}> <SyncComponent /> </ErrorBoundary> </body> </html> ) }) async function AsyncComponent() { await new Promise((resolve) => setTimeout(resolve, 2000)) throw new Error('Error') return <div>Hello</div> } app.get('/with-suspense', async (c) => { return c.html( <html> <body> <ErrorBoundary fallback={<div>Out of Service</div>}> <Suspense fallback={<div>Loading...</div>}> <AsyncComponent /> </Suspense> </ErrorBoundary> </body> </html> ) })

Example: StreamingContext with nonce

import { Suspense, StreamingContext } from 'hono/jsx/streaming' app.get('/', (c) => { const stream = renderToReadableStream( <html> <body> <StreamingContext value={{ scriptNonce: 'random-nonce-value' }} > <Suspense fallback={<div>Loading...</div>}> <AsyncComponent /> </Suspense> </StreamingContext> </body> </html> ) return c.body(stream, { headers: { 'Content-Type': 'text/html; charset=UTF-8', 'Transfer-Encoding': 'chunked', 'Content-Security-Policy': "script-src 'nonce-random-nonce-value'", }, }) })

CSS helpers security and injection prevention

The css helpers are raw CSS sinks. They block breaking out into HTML by filtering quotes, backslashes, and </, but {}, and ; pass through as valid CSS. Do not pass untrusted input directly. Validate input against an allowlist before using it in css template literals.

css helper import and basic usage

Import the css helper from 'hono/css'. The css function is a template literal that writes CSS in JSX. It returns a class name that is set as the value of the class attribute. The <Style /> component must be included to render the CSS content.

css pseudo-class syntax with nesting selector

Use the CSS nesting selector & to style pseudo-classes like :hover within a css template literal. Example: css`background-color: #fff; &:hover { background-color: red; }`

css class extension and composition

You can extend CSS definitions by embedding a class name in another css template literal. Use the syntax ${baseClass} to reference a previously defined class, and you can nest selectors with ${headerClass} { selector { } } syntax to apply styles to nested elements.

keyframes for CSS animations

The keyframes function writes the contents of @keyframes rules. The return value is the animation name that can be used in the animation-name property of a css template literal.

:-hono-global pseudo-selector for global styles

The :-hono-global pseudo-selector allows you to define global styles within a css template literal. Alternatively, you can pass css literals directly to the <Style /> component to define global styles.

cx function composites class names

The cx function composes two or more class names together. It can combine css template literal results and simple string class names. Example: cx(buttonClass, primaryClass) or cx('h1', primaryClass)

Style component with nonce for CSP headers

When using the css helpers with the Secure Headers middleware and Content-Security-Policy, add the nonce attribute to the <Style /> component: <Style nonce={c.get('secureHeadersNonce')} />. Set styleSrc to [NONCE] in the secureHeaders middleware configuration.

createCssContext for custom CSS configuration

createCssContext creates custom css, cx, keyframes, viewTransition, and Style functions. It accepts options: id (custom style element ID), classNameSlug (function to generate custom class names), and onInvalidSlug (function to handle invalid class names).

classNameSlug function signature and parameters

The classNameSlug function receives three arguments: hash (default generated class name like 'css-1234567890'), label (extracted from a comment at the start of the CSS template, or empty string), and css (the minified CSS string). Return a custom class name string.

onInvalidSlug callback for invalid class names

The onInvalidSlug option is a function that receives the invalid slug as an argument. By default, a warning is logged. You can customize this to throw an error or handle it differently.

html helper in JSX for inline scripts

Insert html template literals directly into JSX to embed inline scripts without needing dangerouslySetInnerHTML. The script content will not be escaped when written inside html`` tags within JSX.

Extending ContextRenderer for custom props

Extend ContextRenderer interface in Hono module to pass additional props to renderer. Declare module 'hono' with interface ContextRenderer accepting content and custom props object. Example: interface ContextRenderer { (content: string | Promise<string>, props: { title: string }): Response }. Then use c.render(jsx, { title: 'value' }) to pass props.

JSX Renderer Middleware import

Import JSX Renderer Middleware with `import { Hono } from 'hono'` and `import { jsxRenderer, useRequestContext } from 'hono/jsx-renderer'`.

jsxRenderer basic usage

Use jsxRenderer as middleware to set up layout for c.render(). Pass a function that receives {children} and returns JSX wrapping the children. Example: app.get('/page/*', jsxRenderer(({ children }) => <html><body><header>Menu</header><div>{children}</div></body></html>)). Then call c.render() with JSX content in route handlers.

jsxRenderer docType option

The docType option is optional and accepts boolean or string. If false, no DOCTYPE is added to the HTML. If a string, the custom DOCTYPE is used instead of the default. Default behavior adds a DOCTYPE.

jsxRenderer stream option

The stream option is optional and accepts boolean or Record<string, string>. If true or a Record value is provided, renders as streaming response. When true, adds headers: 'Transfer-Encoding': 'chunked', 'Content-Type': 'text/html; charset=UTF-8', 'Content-Encoding': 'Identity'. Record values customize header values.

jsxRenderer stream with async components

Stream option enables rendering async components with Suspense. Example: jsxRenderer(({ children }) => <html><body><h1>SSR Streaming</h1>{children}</body></html>, { stream: true }). Components can use async/await and Suspense fallback.

jsxRenderer function-based options

Instead of a static options object, pass a function that receives Context object. This allows dynamic option setting based on request context. Example: jsxRenderer(layoutFn, (c) => ({ stream: c.req.header('X-Enable-Streaming') === 'true' })). Useful for enabling/disabling features based on request headers or environment.

jsxRenderer with SSG context

Use isSSGContext helper with function-based options to disable streaming during static site generation: jsxRenderer(layoutFn, (c) => ({ stream: !isSSGContext(c) })). This prevents streaming when generating static sites.

Nested layouts with Layout component

Enable nested layouts by using the Layout component prop. Parent layout applies jsxRenderer() with standard layout. Child app applies jsxRenderer with Layout prop: jsxRenderer(({ children, Layout }) => <Layout><nav>Blog Menu</nav><div>{children}</div></Layout>). Mount child app to parent with app.route('/blog', blog).

useRequestContext hook

useRequestContext() returns the Context instance from within JSX components. Use to access request data like url: const c = useRequestContext(); return <b>{c.req.url}</b>. Enables components to access request context without passing through props.

useRequestContext incompatibility with Deno precompile JSX

useRequestContext() cannot be used with Deno's precompile JSX option. Use 'react-jsx' instead in tsconfig.json: set compilerOptions.jsx to 'react-jsx' and jsxImportSource to 'hono/jsx'.

c.render with extended ContextRenderer props

Call c.render(jsx, { customProps }) to pass additional properties to the renderer layout function. Example: c.render(<div>content</div>, { title: 'My favorites' }) where layout receives title in destructuring: jsxRenderer(({ children, title }) => ...).

Give your agent this brain