Hono React
Directory Structure
.
├── package.json
├── src
│ ├── app.tsx
│ ├── index.tsx
│ └── main.tsx
├── tsconfig.json
└── vite.config.ts
Install
sh
pnpm add react react-dom hono @hono/zod-openapi
sh
pnpm add -D @types/react @types/react-dom vite @hono/vite-dev-server @hono/swagger-ui
app.tsx
tsx
import { useState } from 'react'
import { client } from './'
const App = () => {
const [message, setMessage] = useState('')
const onSubmit = async () => {
const res = await client.$get()
const data = await res.json()
setMessage(data.message)
}
return (
<>
<h1>Hono🔥 React</h1>
<button type='button' onClick={onSubmit}>
Get Message
</button>
<h1>{message}</h1>
</>
)
}
export default App
index.tsx
tsx
import { OpenAPIHono, createRoute, z } from '@hono/zod-openapi'
import type { RouteHandler } from '@hono/zod-openapi'
import { hc } from 'hono/client'
import { swaggerUI } from '@hono/swagger-ui'
import { renderToString } from 'react-dom/server'
const app = new OpenAPIHono()
const get = createRoute({
tags: ['Hono'],
method: 'get',
path: '/',
description: 'Hono🔥 React',
responses: {
200: {
description: 'Hono🔥',
content: {
'application/json': {
schema: z.object({
message: z.string(),
}),
},
},
},
},
})
export const getHandler: RouteHandler<typeof get> = async (c) => {
return c.json({ message: 'Hono🔥 React' })
}
export const api = app.basePath('/api').openapi(get, getHandler)
// Swagger
api
.doc('/doc', {
info: {
title: 'Hono API',
version: 'v1',
},
openapi: '3.1.0',
tags: [
{
name: 'Hono',
description: 'Hono API',
},
],
})
.get('/ui', swaggerUI({ url: '/api/doc' }))
type AddType = typeof api
export const client = hc<AddType>('/').api
app.get('*', (c) => {
return c.html(
renderToString(
<html lang='en'>
<head>
<meta charSet='utf-8' />
<meta content='width=device-width, initial-scale=1' name='viewport' />
<title>Hono🔥 React</title>
<script type='module' src='/src/main.tsx' />
</head>
<body>
<div id='root' />
</body>
</html>,
),
)
})
export default app
main.tsx
tsx
import { createRoot } from 'react-dom/client'
import App from './app'
const rootElement = document.getElementById('root')
const root = rootElement ? createRoot(rootElement) : console.error('Root element not found')
if (root) {
root.render(<App />)
}
vite.config.ts
ts
import { defineConfig } from 'vite'
import devServer from '@hono/vite-dev-server'
export default defineConfig({
plugins: [
devServer({
entry: 'src/index.tsx',
}),
],
})