npm hono 3.8.0
v3.8.0

latest releases: 4.6.9, 4.6.8, 4.6.7...
12 months ago

Hono v3.8.0 is out now! Let's take a look at the new features.

JSX Context API

The new feature for JSX. By using useContext(), you can share data globally across any level of the Component tree without passing values through props.

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>
  )
})

Thanks @usualoma!

JSX Renderer Middleware

JSX Renderer Middleware allows you to set up the layout when rendering JSX with the c.render() function, without the need for using c.setRenderer(). Additionally, it enables access to instances of Context within components through the use of useRequestContext().

import { Hono } from 'hono'
import { jsxRenderer, useRequestContext } from 'hono/jsx-renderer'

const app = new Hono()

const RequestUrlBadge: FC = () => {
  const c = useRequestContext()
  return <b>{c.req.url}</b>
}

app.get(
  '/page/*',
  jsxRenderer(({ children }) => {
    return (
      <html>
        <body>
          <nav>Menu</nav>
          <div>{children}</div>
        </body>
      </html>
    )
  })
)

app.get('/page/about', (c) => {
  return c.render(
    <>
      <h1>About me!</h1>
      <div>
        You are accessing: <RequestUrlBadge />
      </div>
    </>
  )
})

Thanks @usualoma!

Streaming Helper

The streaming Helper provides a method to extend c.stream(). streamSSE() allows you to stream Server-Sent Events (SSE) seamlessly.

import { Hono } from 'hono'
import { streamSSE } from 'hono/streaming'

const app = new Hono()

app.get('/sse', async (c) => {
  return streamSSE(c, async (stream) => {
    while (true) {
      const message = `It is ${new Date().toISOString()}`
      await stream.writeSSE({ data: message })
      await stream.sleep(1000)
    }
  })
})

Thanks @watany-dev!

Factory Helper

The Factory Helper provides useful functions for creating Hono's components such as Middleware. Sometimes it's difficult to set the proper TypeScript types, but this helper facilitates that.

createMiddleware() that is added this version will create your custom middleware.

import { Hono } from 'hono'
import { createMiddleware } from 'hono/factory'

const messageMiddleware = createMiddleware(async (c, next) => {
  await next()
  c.res.headers.set('X-Message', 'Good morning!')
})

Thanks @arunavabasu-03 for helping!

parseBody() supports multi values

Now, c.req.parseBody() supports multi values.

If the key is foo[], it will be (string | File)[].

const body = await c.req.parseBody()
body['foo[]']

And, you can use the all option.

const body = await c.req.parseBody({ all: true })
body['foo']

Thanks @sor4chi!

Improve path matching in the router

Improved the path matching in the router. Previously, for instance, a Duplicate param name error would be thrown if there were parameters with the same name, type, url, as shown below:

app.get('/:type/:url', (c) => {
  return c.text(`type: ${c.req.param('type')}, url: ${c.req.param('url')}`)
})

app.get('/foo/:type/:url', (c) => {
  return c.text(`foo type: ${c.req.param('type')}, url: ${c.req.param('url')}`)
})

With this improvement, the error is no longer thrown, and the correct parameter values can be obtained in each handler.

Thanks @usualoma!

All Updates

New Contributors

  • @arunavabasu-03 made their first contribution in #1540

Full Changelog: v3.7.6...v3.8.0

Don't miss a new hono release

NewReleases is sending notifications on new releases.