Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

HTML на JSX

Кроме JSON, Hono умеет отдавать HTML-страницы. Писать разметку строками неудобно и опасно, поэтому в Hono встроен JSX — синтаксис, в котором HTML-теги пишутся прямо в коде TypeScript. Это не React: JSX Hono просто превращает разметку в строку HTML на сервере, без кода в браузере.

Настройка

Файлы с JSX должны иметь расширение .tsx. В tsconfig.json проекта уже есть нужные строки, проверьте их:

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "hono/jsx"
  }
}

Вторая строка говорит TypeScript брать JSX из Hono, а не из React. Устанавливать ничего не нужно.

Первая страница

Создайте src/routes/pages.tsx:

// src/routes/pages.tsx
import { Hono } from 'hono'
 
const pages = new Hono()
 
pages.get('/', (c) => {
  return c.html(<h1>Блог о программировании</h1>)
})
 
export default pages

Подключите группу в src/index.ts строкой app.route('/', pages) с импортом import pages from './routes/pages.js'. Откройте http://localhost:3000/ — появится заголовок. c.html() принимает JSX и сам ставит заголовок Content-Type: text/html.

Компонент

Компонент — функция, которая возвращает разметку. Её имя пишут с большой буквы и используют как тег:

// src/components/PostCard.tsx
import type { FC } from 'hono/jsx'
 
type Props = {
  title: string
  body: string
}
 
export const PostCard: FC<Props> = ({ title, body }) => {
  return (
    <article>
      <h2>{title}</h2>
      <p>{body}</p>
    </article>
  )
}

Данные приходят в компонент через props — объект с атрибутами, указанными при использовании тега. Значения в фигурных скобках экранируются: если в заголовке окажется тег script, он выведется как текст и не выполнится.

Использование компонента и список

Выведите все статьи на странице /posts:

// src/routes/pages.tsx
import { PostCard } from '../components/PostCard.js'
 
const posts = [
  { id: 1, title: 'Первая статья', body: 'Привет, мир!' },
  { id: 2, title: 'Вторая статья', body: 'Учим Hono.' },
]
 
pages.get('/posts', (c) => {
  return c.html(
    <main>
      <h1>Статьи</h1>
      {posts.map((post) => (
        <PostCard title={post.title} body={post.body} />
      ))}
    </main>,
  )
})

Страница http://localhost:3000/posts покажет заголовок и две карточки статей. Список строится обычным map(). Ключи key, как в React, здесь не нужны: страница собирается один раз на сервере.

Отличия от HTML

HTMLJSX
class="post"class="post" — в Hono можно писать как в HTML
<input><input /> — одиночный тег закрывается
текст с даннымивыражение в фигурных скобках
onclick="..."обработчики событий на сервере не работают

Частая ошибка

Код с JSX пишут в файле .ts. TypeScript не разбирает разметку в таких файлах и выдаёт множество непонятных ошибок. Переименуйте файл в .tsx, а в импортах по-прежнему указывайте .js: ../components/PostCard.js.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.