Hono: JSX templates

We’ve previously seen how to render some HTML using c.html().

Hono lets you write your server responses as JSX, which I think it’s the optimal way of mixing HTML markup and JavaScript data.

JSX is the templating engine introduced by React, and now used in many other libraries too. React is a UI library and runs in the browser.

In this case, we have Hono that is a server-side framework.

And we use JSX to generate HTML on the server.

There is no React involved in this, except at a very low level (and transparent to you) to generate HTML from JSX.

To use JSX, we import it at the top of the index.js file:

/** @jsx jsx */
import { jsx } from 'hono/jsx'

Now we can use JSX in our Hono responses:

app.get('/', (c) => {
  const numbers = ['one', 'two', 'three']

  return c.html(
    <html>
      <head>
        <title>test</title>
      </head>
      <body>
        <h1>test</h1>
        {numbers.map((num) => (
          <p>{num}</p>
        ))}
      </body>
    </html>
  )
})

If this is the first time you see JSX, it seems strange at first, but look at what we don’t need any more: we don’t need a template literal. And we don’t need to do that annoying “HTML string building” we did before:

${numbers.map((num) => '<p>' + num + '</p>').join('\n')}

now we use a much cleaner syntax, embedding data using the {expression} syntax.

And this is just the beginning.

Because now you can start doing what JSX unlocks: components-based UI building.

We can create our first component in the file, let’s call it Numbers:

const Numbers = () => {
  const numbers = ['one', 'two', 'three']

  return (
    <div>
      {numbers.map((num) => (
        <p>{num}</p>
      ))}
    </div>
  )
}

and we can use it in the app.get('/') callback:

app.get('/', (c) => {
  return c.html(
    <html>
      <head>
        <title>test</title>
      </head>
      <body>
        <h1>test</h1>
        <Numbers />
      </body>
    </html>
  )
})

We could also pass the numbers data as a prop to the Numbers component:

const Numbers = ({ numbers }) => {
  return (
    <div>
      {numbers.map((num) => (
        <p>{num}</p>
      ))}
    </div>
  )
}

app.get('/', (c) => {
  const numbers = ['one', 'two', 'three']

  return c.html(
    <html>
      <head>
        <title>test</title>
      </head>
      <body>
        <h1>test</h1>
        <Numbers numbers={numbers} />
      </body>
    </html>
  )
})

We can also move components to different files as the application grows in complexity.

This looks like a React application, right?

Except this is server-side, so we can’t use things like useState, useEffect, and all the other frontend-facing functionality.

But it’s still a great way to build a UI on the server.

Lessons in this unit:

0: Introduction
1: Your first Hono app
2: The Request object
3: Send a response to the client
4: Manage cookies
5: Work with HTTP headers
6: Handling redirects
7: Routing
8: ▶︎ JSX templates
9: Middleware
10: Hono on Node.js
11: Handling forms COMING SOON
Are you intimidated by Git? Can’t figure out merge vs rebase? Are you afraid of screwing up something any time you have to do something in Git? Do you rely on ChatGPT or random people’s answer on StackOverflow to fix your problems? Your coworkers are tired of explaining Git to you all the time? Git is something we all need to use, but few of us really master it. I created this course to improve your Git (and GitHub) knowledge at a radical level. Launching May 21, 2024. Join the waiting list!