客戶端元件
hono/jsx
不僅支援伺服器端,也支援客戶端。這意味著可以建立在瀏覽器中執行的互動式 UI。我們稱之為客戶端元件或 hono/jsx/dom
。
它速度快且體積非常小。hono/jsx/dom
中的計數器程式使用 Brotli 壓縮後僅有 2.8KB。但 React 則為 47.8KB。
本節介紹客戶端元件特定的功能。
計數器範例
以下是一個簡單計數器的範例,與 React 中的程式碼相同。
import { useState } from 'hono/jsx'
import { render } from 'hono/jsx/dom'
function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
)
}
function App() {
return (
<html>
<body>
<Counter />
</body>
</html>
)
}
const root = document.getElementById('root')
render(<App />, root)
render()
您可以使用 render()
在指定的 HTML 元素中插入 JSX 元件。
render(<Component />, container)
與 React 相容的 Hook
hono/jsx/dom 具有與 React 相容或部分相容的 Hook。您可以透過查看 React 文件來了解這些 API。
useState()
useEffect()
useRef()
useCallback()
use()
startTransition()
useTransition()
useDeferredValue()
useMemo()
useLayoutEffect()
useReducer()
useDebugValue()
createElement()
memo()
isValidElement()
useId()
createRef()
forwardRef()
useImperativeHandle()
useSyncExternalStore()
useInsertionEffect()
useFormStatus()
useActionState()
useOptimistic()
startViewTransition()
系列
startViewTransition()
系列包含用於輕鬆處理 View Transitions API 的原始 Hook 和函式。以下是如何使用它們的範例。
1. 最簡單的範例
您可以使用 startViewTransition()
簡短地使用 document.startViewTransition
來編寫轉換。
import { useState, startViewTransition } from 'hono/jsx'
import { css, Style } from 'hono/css'
export default function App() {
const [showLargeImage, setShowLargeImage] = useState(false)
return (
<>
<Style />
<button
onClick={() =>
startViewTransition(() =>
setShowLargeImage((state) => !state)
)
}
>
Click!
</button>
<div>
{!showLargeImage ? (
<img src='https://hono.dev.org.tw/images/logo.png' />
) : (
<div
class={css`
background: url('https://hono.dev.org.tw/images/logo-large.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
width: 600px;
height: 600px;
`}
></div>
)}
</div>
</>
)
}
2. 使用 viewTransition()
與 keyframes()
viewTransition()
函式可讓您取得唯一的 view-transition-name
。
您可以將其與 keyframes()
一起使用,::view-transition-old()
會轉換為 ::view-transition-old(${uniqueName}))
。
import { useState, startViewTransition } from 'hono/jsx'
import { viewTransition } from 'hono/jsx/dom/css'
import { css, keyframes, Style } from 'hono/css'
const rotate = keyframes`
from {
rotate: 0deg;
}
to {
rotate: 360deg;
}
`
export default function App() {
const [showLargeImage, setShowLargeImage] = useState(false)
const [transitionNameClass] = useState(() =>
viewTransition(css`
::view-transition-old() {
animation-name: ${rotate};
}
::view-transition-new() {
animation-name: ${rotate};
}
`)
)
return (
<>
<Style />
<button
onClick={() =>
startViewTransition(() =>
setShowLargeImage((state) => !state)
)
}
>
Click!
</button>
<div>
{!showLargeImage ? (
<img src='https://hono.dev.org.tw/images/logo.png' />
) : (
<div
class={css`
${transitionNameClass}
background: url('https://hono.dev.org.tw/images/logo-large.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
width: 600px;
height: 600px;
`}
></div>
)}
</div>
</>
)
}
3. 使用 useViewTransition
如果您只想在動畫期間變更樣式。您可以使用 useViewTransition()
。這個 Hook 會傳回 [boolean, (callback: () => void) => void]
,它們是 isUpdating
標誌和 startViewTransition()
函式。
當使用此 Hook 時,元件會在以下兩個時間進行評估。
- 在呼叫
startViewTransition()
的回呼函式內部。 - 當
finish
promise 變成已實現 時
import { useState, useViewTransition } from 'hono/jsx'
import { viewTransition } from 'hono/jsx/dom/css'
import { css, keyframes, Style } from 'hono/css'
const rotate = keyframes`
from {
rotate: 0deg;
}
to {
rotate: 360deg;
}
`
export default function App() {
const [isUpdating, startViewTransition] = useViewTransition()
const [showLargeImage, setShowLargeImage] = useState(false)
const [transitionNameClass] = useState(() =>
viewTransition(css`
::view-transition-old() {
animation-name: ${rotate};
}
::view-transition-new() {
animation-name: ${rotate};
}
`)
)
return (
<>
<Style />
<button
onClick={() =>
startViewTransition(() =>
setShowLargeImage((state) => !state)
)
}
>
Click!
</button>
<div>
{!showLargeImage ? (
<img src='https://hono.dev.org.tw/images/logo.png' />
) : (
<div
class={css`
${transitionNameClass}
background: url('https://hono.dev.org.tw/images/logo-large.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
width: 600px;
height: 600px;
position: relative;
${isUpdating &&
css`
&:before {
content: 'Loading...';
position: absolute;
top: 50%;
left: 50%;
}
`}
`}
></div>
)}
</div>
</>
)
}
hono/jsx/dom
執行階段
有一個用於客戶端元件的小型 JSX 執行階段。使用它將產生比使用 hono/jsx
更小的捆綁結果。在 tsconfig.json
中指定 hono/jsx/dom
。
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx/dom"
}
}