mirror of
https://github.com/honojs/hono.git
synced 2024-11-21 18:18:57 +01:00
[BREAKING] refactor(jsx): h
to jsx
, remove h
(#318)
This commit is contained in:
parent
21aabc44f4
commit
d43321109d
@ -2,7 +2,7 @@
|
||||
|
||||
JSX Middleware enable rendering HTML with JSX syntax.
|
||||
It's just for Sever-Side-Rendering. No virtual DOM.
|
||||
This middleware supports only for TypeScript.
|
||||
This middleware is only for writing with TypeScript.
|
||||
|
||||
## Settings
|
||||
|
||||
@ -12,7 +12,8 @@ tsconfig.json:
|
||||
{
|
||||
"compilerOptions": {
|
||||
"jsx": "react",
|
||||
"jsxFactory": "h"
|
||||
"jsxFactory": "jsx",
|
||||
"jsxFragmentFactory": "Fragment"
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -23,12 +24,10 @@ index.tsx:
|
||||
|
||||
```tsx
|
||||
import { Hono } from 'hono'
|
||||
import { h, jsx } from 'hono/jsx'
|
||||
import { jsx } from 'hono/jsx'
|
||||
|
||||
const app = new Hono()
|
||||
|
||||
app.use('*', jsx())
|
||||
|
||||
const Layout = (props: { children?: string }) => {
|
||||
return (
|
||||
<html>
|
||||
@ -52,7 +51,7 @@ const Top = (props: { messages: string[] }) => {
|
||||
|
||||
app.get('/', (c) => {
|
||||
const messages = ['Good Morning', 'Good Evening', 'Good Night']
|
||||
return c.render(<Top messages={messages} />)
|
||||
return c.htm(<Top messages={messages} />)
|
||||
})
|
||||
|
||||
app.fire()
|
||||
@ -60,13 +59,47 @@ app.fire()
|
||||
|
||||
## dangerouslySetInnerHTML
|
||||
|
||||
`dangerouslySetInnerHTML` allows you to set HTML directly.
|
||||
|
||||
```tsx
|
||||
app.get('/foo', (c) => {
|
||||
const html = { __html: 'JSX · SSR' }
|
||||
return c.render(<div dangerouslySetInnerHTML={html} />)
|
||||
const inner = { __html: 'JSX · SSR' }
|
||||
const Div = <div dangerouslySetInnerHTML={inner} />
|
||||
})
|
||||
```
|
||||
|
||||
## memo
|
||||
|
||||
You can memorize calculated strings of the component with `memo`.
|
||||
|
||||
```tsx
|
||||
import { jsx, memo } from 'hono/jsx'
|
||||
|
||||
const Header = memo(() => <header>Welcome to Hono</header>)
|
||||
const Footer = memo(() => <footer>Powered by Hono</footer>)
|
||||
const Layout = (
|
||||
<div>
|
||||
<Header />
|
||||
<p>Hono is cool!</p>
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
```
|
||||
|
||||
## Fragment
|
||||
|
||||
```tsx
|
||||
import { jsx, Fragment } from 'hono/jsx'
|
||||
|
||||
const List = () => (
|
||||
<Fragment>
|
||||
<p>first child</p>
|
||||
<p>second child</p>
|
||||
<p>third child</p>
|
||||
</Fragment>
|
||||
)
|
||||
```
|
||||
|
||||
## Tips for Cloudflare Workers
|
||||
|
||||
It's useful to use Miniflare's`live-reload` option for developing.
|
||||
|
@ -1,18 +1,17 @@
|
||||
import { Hono } from '../../hono'
|
||||
import { h, jsx, memo, Fragment } from '.'
|
||||
import { jsx, memo, Fragment } from '.'
|
||||
|
||||
describe('JSX middleware', () => {
|
||||
const app = new Hono()
|
||||
app.use('*', jsx())
|
||||
|
||||
it('Should render HTML strings', async () => {
|
||||
app.get('/', (c) => {
|
||||
return c.render(<h1>Hello</h1>)
|
||||
return c.html(<h1>Hello</h1>)
|
||||
})
|
||||
const res = await app.request('http://localhost/')
|
||||
expect(res.status).toBe(200)
|
||||
expect(res.headers.get('Content-Type')).toBe('text/html; charset=UTF-8')
|
||||
expect(await res.text()).toBe('<!doctype html><h1>Hello</h1>')
|
||||
expect(await res.text()).toBe('<h1>Hello</h1>')
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -1,28 +1,16 @@
|
||||
import type { Context } from '../../context'
|
||||
import type { Next } from '../../hono'
|
||||
import { escape } from '../../utils/html'
|
||||
import type { HtmlEscapedString } from '../../utils/html'
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
namespace h.JSX {
|
||||
namespace jsx.JSX {
|
||||
interface IntrinsicElements {
|
||||
[tagName: string]: Record<string, any>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const jsx = () => {
|
||||
return async (c: Context, next: Next) => {
|
||||
c.render = (content: string) => {
|
||||
const output = `<!doctype html>${content.toString()}`
|
||||
return c.html(output)
|
||||
}
|
||||
await next()
|
||||
}
|
||||
}
|
||||
|
||||
export const h = (
|
||||
export const jsx = (
|
||||
tag: string | Function,
|
||||
props: Record<string, any>,
|
||||
...children: (string | HtmlEscapedString)[]
|
||||
@ -116,5 +104,5 @@ export const memo = <T>(
|
||||
}
|
||||
|
||||
export const Fragment = (props: { key?: string; children?: any }): HtmlEscapedString => {
|
||||
return h('', {}, ...(props.children || []))
|
||||
return jsx('', {}, ...(props.children || []))
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
"@cloudflare/workers-types"
|
||||
],
|
||||
"jsx": "react",
|
||||
"jsxFactory": "h",
|
||||
"jsxFactory": "jsx",
|
||||
"jsxFragmentFactory": "Fragment",
|
||||
},
|
||||
"include": [
|
||||
|
Loading…
Reference in New Issue
Block a user