honox
honox copied to clipboard
Nested islands hydrate error 2
What version of HonoX are you using?
0.1.15
What steps can reproduce the bug?
If we have the following an island component:
// app/islands/badge.tsx
import { PropsWithChildren } from 'react'
export default function Badge({ name, children }: PropsWithChildren<{ name: string }>) {
return (
<div>
Hey {name}
<hr />
{children}
</div>
)
}
Then, specify the same island as a child of the island:
// app/routes/index.tsx
import { createRoute } from 'honox/factory'
import Badge from '../islands/badge'
export default createRoute((c) => {
const name = c.req.query('name') ?? 'Hono'
return c.render(
<>
<Badge name="parent">
<Badge name="child" />
</Badge>
</>
)
})
What is the expected behavior?
It does not throw errors.
What do you see instead?
It seems to be rendered correctly, but a hydration error will be shown with React:
This occurs because the HTML rendered by the server is different from the result hydrated by the client:
Server-rendered HTML:
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script type="module" src="/app/client.ts"></script>
</head>
<body>
<honox-island component-name="/islands/badge.tsx" data-serialized-props='{"name":"parent"}'>
<div>
Hey
<!-- -->
parent
<hr />
<honox-island component-name="/islands/badge.tsx" data-serialized-props='{"name":"child"}'>
<div>
Hey
<!-- -->
child
<hr />
</div>
</honox-island>
</div>
<template data-hono-template="">
<honox-island component-name="/islands/badge.tsx" data-serialized-props='{"name":"child"}'>
<div>
Hey
<!-- -->
child
<hr />
</div>
</honox-island>
</template>
</honox-island>
</body>
</html>
<script>
import('/@vite/client')
</script>
The elements rendered by client:
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script type="module" src="/app/client.ts"></script>
</head>
<body data-new-gr-c-s-check-loaded="14.1168.0" data-gr-ext-installed="">
<honox-island
component-name="/islands/badge.tsx"
data-serialized-props='{"name":"parent"}'
data-hono-hydrated="true"
><div>
Hey parent
<hr />
<div>
Hey child
<hr />
</div></div
></honox-island>
<script>
import('/@vite/client')
</script>
</body>
</html>
The minimal project to reproduce it: https://github.com/yusukebe/honox-react-nested-islands/tree/island-in-island
Additional information
#151 solved the problem of normal components in the island, but did not solve this problem.
I think the resulting HTML from the client hydrate should be the same as what the server rendered.
What about the following PR approach? https://github.com/honojs/honox/pull/161
The errors in the following projects will be resolved, and the expected results will be achieved. https://github.com/yusukebe/honox-react-nested-islands/tree/island-in-island
This was fixed! Thanks @usualoma !