Composants côté client
hono/jsx prend en charge le rendu côté serveur et côté client. Vous pouvez donc créer une interface interactive qui s'exécute dans le navigateur. Nous appelons cela les composants côté client, ou hono/jsx/dom.
C'est rapide et très léger. Le programme de compteur avec hono/jsx/dom ne pèse que 2,8 Ko avec la compression Brotli, contre 47,8 Ko pour React.
Cette section présente les fonctionnalités propres aux composants côté client.
Exemple de compteur
Voici un exemple de compteur simple, dont le code fonctionne comme avec 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()
Vous pouvez utiliser render() pour insérer des composants JSX dans un élément HTML donné.
render(<Component />, container)Vous trouverez le code complet ici : exemple de compteur.
Hooks compatibles avec React
hono/jsx/dom propose des hooks compatibles ou partiellement compatibles avec React. Vous pouvez découvrir ces API dans la documentation React.
useState()useEffect()useRef()useCallback()use()startTransition()useTransition()useDeferredValue()useMemo()useLayoutEffect()useReducer()useDebugValue()createElement()memo()isValidElement()useId()createRef()forwardRef()useImperativeHandle()useSyncExternalStore()useInsertionEffect()useFormStatus()useActionState()useOptimistic()
Famille startViewTransition()
La famille startViewTransition() contient des hooks et des fonctions propres à Hono qui facilitent l'utilisation de l'API View Transitions. Les exemples ci-dessous montrent comment les utiliser.
1. Exemple très simple
Vous pouvez écrire de façon concise une transition reposant sur document.startViewTransition avec 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/images/logo.png' />
) : (
<div
class={css`
background: url('https://hono.dev/images/logo-large.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
width: 600px;
height: 600px;
`}
></div>
)}
</div>
</>
)
}2. Utiliser viewTransition() avec keyframes()
La fonction viewTransition() permet d'obtenir un view-transition-name unique.
Vous pouvez l'utiliser avec keyframes() ; ::view-transition-old() est converti en ::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/images/logo.png' />
) : (
<div
class={css`
${transitionNameClass}
background: url('https://hono.dev/images/logo-large.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
width: 600px;
height: 600px;
`}
></div>
)}
</div>
</>
)
}3. Utiliser useViewTransition
Pour changer le style uniquement pendant l'animation, utilisez useViewTransition(). Ce hook renvoie [boolean, (callback: () => void) => void], soit le flag isUpdating et la fonction startViewTransition().
Lorsque ce hook est utilisé, le composant est évalué aux deux moments suivants.
- Dans le callback d'un appel à
startViewTransition(). - Lorsque la promesse
finishest résolue
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/images/logo.png' />
) : (
<div
class={css`
${transitionNameClass}
background: url('https://hono.dev/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>
</>
)
}L'environnement d'exécution hono/jsx/dom
Un petit environnement d'exécution JSX est disponible pour les composants côté client. Il produit des fichiers regroupés plus petits que hono/jsx. Précisez hono/jsx/dom dans tsconfig.json. Avec Deno, modifiez deno.json.
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx/dom"
}
}Vous pouvez aussi préciser hono/jsx/dom dans les options de transformation esbuild de vite.config.ts.
import { defineConfig } from 'vite'
export default defineConfig({
esbuild: {
jsxImportSource: 'hono/jsx/dom',
},
})