0
0
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:
Yusuke Wada 2022-06-13 09:25:27 +09:00 committed by GitHub
parent 21aabc44f4
commit d43321109d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 28 deletions

View File

@ -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 &middot; SSR' }
return c.render(<div dangerouslySetInnerHTML={html} />)
const inner = { __html: 'JSX &middot; 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.

View File

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

View File

@ -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 || []))
}

View File

@ -19,7 +19,7 @@
"@cloudflare/workers-types"
],
"jsx": "react",
"jsxFactory": "h",
"jsxFactory": "jsx",
"jsxFragmentFactory": "Fragment",
},
"include": [